Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(67)

Side by Side Diff: src/IceOperand.h

Issue 1216963007: Doxygenize the documentation comments (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Rebase to master Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/IceLiveness.cpp ('k') | src/IceOperand.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 //===- subzero/src/IceOperand.h - High-level operands -----------*- C++ -*-===// 1 //===- subzero/src/IceOperand.h - High-level operands -----------*- C++ -*-===//
2 // 2 //
3 // The Subzero Code Generator 3 // The Subzero Code Generator
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 // 9 ///
10 // This file declares the Operand class and its target-independent 10 /// \file
11 // subclasses. The main classes are Variable, which represents an 11 /// This file declares the Operand class and its target-independent
12 // LLVM variable that is either register- or stack-allocated, and the 12 /// subclasses. The main classes are Variable, which represents an
13 // Constant hierarchy, which represents integer, floating-point, 13 /// LLVM variable that is either register- or stack-allocated, and the
14 // and/or symbolic constants. 14 /// Constant hierarchy, which represents integer, floating-point,
15 // 15 /// and/or symbolic constants.
16 ///
16 //===----------------------------------------------------------------------===// 17 //===----------------------------------------------------------------------===//
17 18
18 #ifndef SUBZERO_SRC_ICEOPERAND_H 19 #ifndef SUBZERO_SRC_ICEOPERAND_H
19 #define SUBZERO_SRC_ICEOPERAND_H 20 #define SUBZERO_SRC_ICEOPERAND_H
20 21
21 #include "IceCfg.h" 22 #include "IceCfg.h"
22 #include "IceDefs.h" 23 #include "IceDefs.h"
23 #include "IceGlobalContext.h" 24 #include "IceGlobalContext.h"
24 #include "IceTypes.h" 25 #include "IceTypes.h"
25 26
(...skipping 22 matching lines...) Expand all
48 // Target-specific operand classes use kTarget as the starting 49 // Target-specific operand classes use kTarget as the starting
49 // point for their Kind enum space. Note that the value-spaces are shared 50 // point for their Kind enum space. Note that the value-spaces are shared
50 // across targets. To avoid confusion over the definition of shared 51 // across targets. To avoid confusion over the definition of shared
51 // values, an object specific to one target should never be passed 52 // values, an object specific to one target should never be passed
52 // to a different target. 53 // to a different target.
53 kTarget 54 kTarget
54 }; 55 };
55 OperandKind getKind() const { return Kind; } 56 OperandKind getKind() const { return Kind; }
56 Type getType() const { return Ty; } 57 Type getType() const { return Ty; }
57 58
58 // Every Operand keeps an array of the Variables referenced in 59 /// Every Operand keeps an array of the Variables referenced in
59 // the operand. This is so that the liveness operations can get 60 /// the operand. This is so that the liveness operations can get
60 // quick access to the variables of interest, without having to dig 61 /// quick access to the variables of interest, without having to dig
61 // so far into the operand. 62 /// so far into the operand.
62 SizeT getNumVars() const { return NumVars; } 63 SizeT getNumVars() const { return NumVars; }
63 Variable *getVar(SizeT I) const { 64 Variable *getVar(SizeT I) const {
64 assert(I < getNumVars()); 65 assert(I < getNumVars());
65 return Vars[I]; 66 return Vars[I];
66 } 67 }
67 virtual void emit(const Cfg *Func) const = 0; 68 virtual void emit(const Cfg *Func) const = 0;
68 // The dump(Func,Str) implementation must be sure to handle the 69
69 // situation where Func==nullptr. 70 /// \name Dumping functions.
71 /// @{
72
73 /// The dump(Func,Str) implementation must be sure to handle the
74 /// situation where Func==nullptr.
70 virtual void dump(const Cfg *Func, Ostream &Str) const = 0; 75 virtual void dump(const Cfg *Func, Ostream &Str) const = 0;
71 void dump(const Cfg *Func) const { 76 void dump(const Cfg *Func) const {
72 if (!BuildDefs::dump()) 77 if (!BuildDefs::dump())
73 return; 78 return;
74 assert(Func); 79 assert(Func);
75 dump(Func, Func->getContext()->getStrDump()); 80 dump(Func, Func->getContext()->getStrDump());
76 } 81 }
77 void dump(Ostream &Str) const { 82 void dump(Ostream &Str) const {
78 if (BuildDefs::dump()) 83 if (BuildDefs::dump())
79 dump(nullptr, Str); 84 dump(nullptr, Str);
80 } 85 }
86 /// @}
81 87
82 protected: 88 protected:
83 Operand(OperandKind Kind, Type Ty) : Ty(Ty), Kind(Kind) {} 89 Operand(OperandKind Kind, Type Ty) : Ty(Ty), Kind(Kind) {}
84 virtual ~Operand() = default; 90 virtual ~Operand() = default;
85 91
86 const Type Ty; 92 const Type Ty;
87 const OperandKind Kind; 93 const OperandKind Kind;
88 // Vars and NumVars are initialized by the derived class. 94 /// Vars and NumVars are initialized by the derived class.
89 SizeT NumVars = 0; 95 SizeT NumVars = 0;
90 Variable **Vars = nullptr; 96 Variable **Vars = nullptr;
91 }; 97 };
92 98
93 template <class StreamType> 99 template <class StreamType>
94 inline StreamType &operator<<(StreamType &Str, const Operand &Op) { 100 inline StreamType &operator<<(StreamType &Str, const Operand &Op) {
95 Op.dump(Str); 101 Op.dump(Str);
96 return Str; 102 return Str;
97 } 103 }
98 104
99 // Constant is the abstract base class for constants. All 105 /// Constant is the abstract base class for constants. All
100 // constants are allocated from a global arena and are pooled. 106 /// constants are allocated from a global arena and are pooled.
101 class Constant : public Operand { 107 class Constant : public Operand {
102 Constant() = delete; 108 Constant() = delete;
103 Constant(const Constant &) = delete; 109 Constant(const Constant &) = delete;
104 Constant &operator=(const Constant &) = delete; 110 Constant &operator=(const Constant &) = delete;
105 111
106 public: 112 public:
107 void emitPoolLabel(Ostream &Str) const { 113 void emitPoolLabel(Ostream &Str) const {
108 Str << ".L$" << getType() << "$" << PoolEntryID; 114 Str << ".L$" << getType() << "$" << PoolEntryID;
109 } 115 }
110 void emit(const Cfg *Func) const override { emit(Func->getTarget()); } 116 void emit(const Cfg *Func) const override { emit(Func->getTarget()); }
111 virtual void emit(TargetLowering *Target) const = 0; 117 virtual void emit(TargetLowering *Target) const = 0;
112 118
113 static bool classof(const Operand *Operand) { 119 static bool classof(const Operand *Operand) {
114 OperandKind Kind = Operand->getKind(); 120 OperandKind Kind = Operand->getKind();
115 return Kind >= kConst_Base && Kind <= kConst_Num; 121 return Kind >= kConst_Base && Kind <= kConst_Num;
116 } 122 }
117 123
118 // Judge if this given immediate should be randomized or pooled 124 /// Judge if this given immediate should be randomized or pooled
119 // By default should return false, only constant integers should 125 /// By default should return false, only constant integers should
120 // truly go through this method. 126 /// truly go through this method.
121 virtual bool shouldBeRandomizedOrPooled(const GlobalContext *Ctx) { 127 virtual bool shouldBeRandomizedOrPooled(const GlobalContext *Ctx) {
122 (void)Ctx; 128 (void)Ctx;
123 return false; 129 return false;
124 } 130 }
125 131
126 void setShouldBePooled(bool R) { shouldBePooled = R; } 132 void setShouldBePooled(bool R) { shouldBePooled = R; }
127 133
128 bool getShouldBePooled() const { return shouldBePooled; } 134 bool getShouldBePooled() const { return shouldBePooled; }
129 135
130 protected: 136 protected:
131 Constant(OperandKind Kind, Type Ty, uint32_t PoolEntryID) 137 Constant(OperandKind Kind, Type Ty, uint32_t PoolEntryID)
132 : Operand(Kind, Ty), PoolEntryID(PoolEntryID), shouldBePooled(false) { 138 : Operand(Kind, Ty), PoolEntryID(PoolEntryID), shouldBePooled(false) {
133 Vars = nullptr; 139 Vars = nullptr;
134 NumVars = 0; 140 NumVars = 0;
135 } 141 }
136 // PoolEntryID is an integer that uniquely identifies the constant 142 /// PoolEntryID is an integer that uniquely identifies the constant
137 // within its constant pool. It is used for building the constant 143 /// within its constant pool. It is used for building the constant
138 // pool in the object code and for referencing its entries. 144 /// pool in the object code and for referencing its entries.
139 const uint32_t PoolEntryID; 145 const uint32_t PoolEntryID;
140 // Whether we should pool this constant. Usually Float/Double and pooled 146 /// Whether we should pool this constant. Usually Float/Double and pooled
141 // Integers should be flagged true. 147 /// Integers should be flagged true.
142 bool shouldBePooled; 148 bool shouldBePooled;
143 }; 149 };
144 150
145 // ConstantPrimitive<> wraps a primitive type. 151 /// ConstantPrimitive<> wraps a primitive type.
146 template <typename T, Operand::OperandKind K> 152 template <typename T, Operand::OperandKind K>
147 class ConstantPrimitive : public Constant { 153 class ConstantPrimitive : public Constant {
148 ConstantPrimitive() = delete; 154 ConstantPrimitive() = delete;
149 ConstantPrimitive(const ConstantPrimitive &) = delete; 155 ConstantPrimitive(const ConstantPrimitive &) = delete;
150 ConstantPrimitive &operator=(const ConstantPrimitive &) = delete; 156 ConstantPrimitive &operator=(const ConstantPrimitive &) = delete;
151 157
152 public: 158 public:
153 typedef T PrimType; 159 typedef T PrimType;
154 160
155 static ConstantPrimitive *create(GlobalContext *Ctx, Type Ty, PrimType Value, 161 static ConstantPrimitive *create(GlobalContext *Ctx, Type Ty, PrimType Value,
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
191 template <> 197 template <>
192 inline void ConstantInteger32::dump(const Cfg *, Ostream &Str) const { 198 inline void ConstantInteger32::dump(const Cfg *, Ostream &Str) const {
193 if (!BuildDefs::dump()) 199 if (!BuildDefs::dump())
194 return; 200 return;
195 if (getType() == IceType_i1) 201 if (getType() == IceType_i1)
196 Str << (getValue() ? "true" : "false"); 202 Str << (getValue() ? "true" : "false");
197 else 203 else
198 Str << static_cast<int32_t>(getValue()); 204 Str << static_cast<int32_t>(getValue());
199 } 205 }
200 206
201 // Specialization of the template member function for ConstantInteger32 207 /// Specialization of the template member function for ConstantInteger32
202 template <> 208 template <>
203 bool ConstantInteger32::shouldBeRandomizedOrPooled(const GlobalContext *Ctx); 209 bool ConstantInteger32::shouldBeRandomizedOrPooled(const GlobalContext *Ctx);
204 210
205 template <> 211 template <>
206 inline void ConstantInteger64::dump(const Cfg *, Ostream &Str) const { 212 inline void ConstantInteger64::dump(const Cfg *, Ostream &Str) const {
207 if (!BuildDefs::dump()) 213 if (!BuildDefs::dump())
208 return; 214 return;
209 assert(getType() == IceType_i64); 215 assert(getType() == IceType_i64);
210 Str << static_cast<int64_t>(getValue()); 216 Str << static_cast<int64_t>(getValue());
211 } 217 }
212 218
213 // RelocatableTuple bundles the parameters that are used to 219 /// RelocatableTuple bundles the parameters that are used to
214 // construct an ConstantRelocatable. It is done this way so that 220 /// construct an ConstantRelocatable. It is done this way so that
215 // ConstantRelocatable can fit into the global constant pool 221 /// ConstantRelocatable can fit into the global constant pool
216 // template mechanism. 222 /// template mechanism.
217 class RelocatableTuple { 223 class RelocatableTuple {
218 RelocatableTuple() = delete; 224 RelocatableTuple() = delete;
219 RelocatableTuple &operator=(const RelocatableTuple &) = delete; 225 RelocatableTuple &operator=(const RelocatableTuple &) = delete;
220 226
221 public: 227 public:
222 RelocatableTuple(const RelocOffsetT Offset, const IceString &Name, 228 RelocatableTuple(const RelocOffsetT Offset, const IceString &Name,
223 bool SuppressMangling) 229 bool SuppressMangling)
224 : Offset(Offset), Name(Name), SuppressMangling(SuppressMangling) {} 230 : Offset(Offset), Name(Name), SuppressMangling(SuppressMangling) {}
225 RelocatableTuple(const RelocatableTuple &) = default; 231 RelocatableTuple(const RelocatableTuple &) = default;
226 232
227 const RelocOffsetT Offset; 233 const RelocOffsetT Offset;
228 const IceString Name; 234 const IceString Name;
229 bool SuppressMangling; 235 bool SuppressMangling;
230 }; 236 };
231 237
232 bool operator==(const RelocatableTuple &A, const RelocatableTuple &B); 238 bool operator==(const RelocatableTuple &A, const RelocatableTuple &B);
233 239
234 // ConstantRelocatable represents a symbolic constant combined with 240 /// ConstantRelocatable represents a symbolic constant combined with
235 // a fixed offset. 241 /// a fixed offset.
236 class ConstantRelocatable : public Constant { 242 class ConstantRelocatable : public Constant {
237 ConstantRelocatable() = delete; 243 ConstantRelocatable() = delete;
238 ConstantRelocatable(const ConstantRelocatable &) = delete; 244 ConstantRelocatable(const ConstantRelocatable &) = delete;
239 ConstantRelocatable &operator=(const ConstantRelocatable &) = delete; 245 ConstantRelocatable &operator=(const ConstantRelocatable &) = delete;
240 246
241 public: 247 public:
242 static ConstantRelocatable *create(GlobalContext *Ctx, Type Ty, 248 static ConstantRelocatable *create(GlobalContext *Ctx, Type Ty,
243 const RelocatableTuple &Tuple, 249 const RelocatableTuple &Tuple,
244 uint32_t PoolEntryID) { 250 uint32_t PoolEntryID) {
245 assert(!Ctx->isIRGenerationDisabled() && 251 assert(!Ctx->isIRGenerationDisabled() &&
(...skipping 15 matching lines...) Expand all
261 static bool classof(const Operand *Operand) { 267 static bool classof(const Operand *Operand) {
262 OperandKind Kind = Operand->getKind(); 268 OperandKind Kind = Operand->getKind();
263 return Kind == kConstRelocatable; 269 return Kind == kConstRelocatable;
264 } 270 }
265 271
266 private: 272 private:
267 ConstantRelocatable(Type Ty, RelocOffsetT Offset, const IceString &Name, 273 ConstantRelocatable(Type Ty, RelocOffsetT Offset, const IceString &Name,
268 bool SuppressMangling, uint32_t PoolEntryID) 274 bool SuppressMangling, uint32_t PoolEntryID)
269 : Constant(kConstRelocatable, Ty, PoolEntryID), Offset(Offset), 275 : Constant(kConstRelocatable, Ty, PoolEntryID), Offset(Offset),
270 Name(Name), SuppressMangling(SuppressMangling) {} 276 Name(Name), SuppressMangling(SuppressMangling) {}
271 const RelocOffsetT Offset; // fixed offset to add 277 const RelocOffsetT Offset; /// fixed offset to add
272 const IceString Name; // optional for debug/dump 278 const IceString Name; /// optional for debug/dump
273 bool SuppressMangling; 279 bool SuppressMangling;
274 }; 280 };
275 281
276 // ConstantUndef represents an unspecified bit pattern. Although it is 282 /// ConstantUndef represents an unspecified bit pattern. Although it is
277 // legal to lower ConstantUndef to any value, backends should try to 283 /// legal to lower ConstantUndef to any value, backends should try to
278 // make code generation deterministic by lowering ConstantUndefs to 0. 284 /// make code generation deterministic by lowering ConstantUndefs to 0.
279 class ConstantUndef : public Constant { 285 class ConstantUndef : public Constant {
280 ConstantUndef() = delete; 286 ConstantUndef() = delete;
281 ConstantUndef(const ConstantUndef &) = delete; 287 ConstantUndef(const ConstantUndef &) = delete;
282 ConstantUndef &operator=(const ConstantUndef &) = delete; 288 ConstantUndef &operator=(const ConstantUndef &) = delete;
283 289
284 public: 290 public:
285 static ConstantUndef *create(GlobalContext *Ctx, Type Ty, 291 static ConstantUndef *create(GlobalContext *Ctx, Type Ty,
286 uint32_t PoolEntryID) { 292 uint32_t PoolEntryID) {
287 assert(!Ctx->isIRGenerationDisabled() && 293 assert(!Ctx->isIRGenerationDisabled() &&
288 "Attempt to build undefined constant when IR generation disabled"); 294 "Attempt to build undefined constant when IR generation disabled");
(...skipping 10 matching lines...) Expand all
299 305
300 static bool classof(const Operand *Operand) { 306 static bool classof(const Operand *Operand) {
301 return Operand->getKind() == kConstUndef; 307 return Operand->getKind() == kConstUndef;
302 } 308 }
303 309
304 private: 310 private:
305 ConstantUndef(Type Ty, uint32_t PoolEntryID) 311 ConstantUndef(Type Ty, uint32_t PoolEntryID)
306 : Constant(kConstUndef, Ty, PoolEntryID) {} 312 : Constant(kConstUndef, Ty, PoolEntryID) {}
307 }; 313 };
308 314
309 // RegWeight is a wrapper for a uint32_t weight value, with a 315 /// RegWeight is a wrapper for a uint32_t weight value, with a
310 // special value that represents infinite weight, and an addWeight() 316 /// special value that represents infinite weight, and an addWeight()
311 // method that ensures that W+infinity=infinity. 317 /// method that ensures that W+infinity=infinity.
312 class RegWeight { 318 class RegWeight {
313 public: 319 public:
314 RegWeight() = default; 320 RegWeight() = default;
315 explicit RegWeight(uint32_t Weight) : Weight(Weight) {} 321 explicit RegWeight(uint32_t Weight) : Weight(Weight) {}
316 RegWeight(const RegWeight &) = default; 322 RegWeight(const RegWeight &) = default;
317 RegWeight &operator=(const RegWeight &) = default; 323 RegWeight &operator=(const RegWeight &) = default;
318 const static uint32_t Inf = ~0; // Force regalloc to give a register 324 const static uint32_t Inf = ~0; /// Force regalloc to give a register
319 const static uint32_t Zero = 0; // Force regalloc NOT to give a register 325 const static uint32_t Zero = 0; /// Force regalloc NOT to give a register
320 void addWeight(uint32_t Delta) { 326 void addWeight(uint32_t Delta) {
321 if (Delta == Inf) 327 if (Delta == Inf)
322 Weight = Inf; 328 Weight = Inf;
323 else if (Weight != Inf) 329 else if (Weight != Inf)
324 Weight += Delta; 330 Weight += Delta;
325 } 331 }
326 void addWeight(const RegWeight &Other) { addWeight(Other.Weight); } 332 void addWeight(const RegWeight &Other) { addWeight(Other.Weight); }
327 void setWeight(uint32_t Val) { Weight = Val; } 333 void setWeight(uint32_t Val) { Weight = Val; }
328 uint32_t getWeight() const { return Weight; } 334 uint32_t getWeight() const { return Weight; }
329 bool isInf() const { return Weight == Inf; } 335 bool isInf() const { return Weight == Inf; }
330 bool isZero() const { return Weight == Zero; } 336 bool isZero() const { return Weight == Zero; }
331 337
332 private: 338 private:
333 uint32_t Weight = 0; 339 uint32_t Weight = 0;
334 }; 340 };
335 Ostream &operator<<(Ostream &Str, const RegWeight &W); 341 Ostream &operator<<(Ostream &Str, const RegWeight &W);
336 bool operator<(const RegWeight &A, const RegWeight &B); 342 bool operator<(const RegWeight &A, const RegWeight &B);
337 bool operator<=(const RegWeight &A, const RegWeight &B); 343 bool operator<=(const RegWeight &A, const RegWeight &B);
338 bool operator==(const RegWeight &A, const RegWeight &B); 344 bool operator==(const RegWeight &A, const RegWeight &B);
339 345
340 // LiveRange is a set of instruction number intervals representing 346 /// LiveRange is a set of instruction number intervals representing
341 // a variable's live range. Generally there is one interval per basic 347 /// a variable's live range. Generally there is one interval per basic
342 // block where the variable is live, but adjacent intervals get 348 /// block where the variable is live, but adjacent intervals get
343 // coalesced into a single interval. LiveRange also includes a 349 /// coalesced into a single interval. LiveRange also includes a
344 // weight, in case e.g. we want a live range to have higher weight 350 /// weight, in case e.g. we want a live range to have higher weight
345 // inside a loop. 351 /// inside a loop.
346 class LiveRange { 352 class LiveRange {
347 public: 353 public:
348 LiveRange() = default; 354 LiveRange() = default;
349 // Special constructor for building a kill set. The advantage is 355 /// Special constructor for building a kill set. The advantage is
350 // that we can reserve the right amount of space in advance. 356 /// that we can reserve the right amount of space in advance.
351 explicit LiveRange(const std::vector<InstNumberT> &Kills) { 357 explicit LiveRange(const std::vector<InstNumberT> &Kills) {
352 Range.reserve(Kills.size()); 358 Range.reserve(Kills.size());
353 for (InstNumberT I : Kills) 359 for (InstNumberT I : Kills)
354 addSegment(I, I); 360 addSegment(I, I);
355 } 361 }
356 LiveRange(const LiveRange &) = default; 362 LiveRange(const LiveRange &) = default;
357 LiveRange &operator=(const LiveRange &) = default; 363 LiveRange &operator=(const LiveRange &) = default;
358 364
359 void reset() { 365 void reset() {
360 Range.clear(); 366 Range.clear();
(...skipping 14 matching lines...) Expand all
375 void untrim() { TrimmedBegin = Range.begin(); } 381 void untrim() { TrimmedBegin = Range.begin(); }
376 void trim(InstNumberT Lower); 382 void trim(InstNumberT Lower);
377 383
378 RegWeight getWeight() const { return Weight; } 384 RegWeight getWeight() const { return Weight; }
379 void setWeight(const RegWeight &NewWeight) { Weight = NewWeight; } 385 void setWeight(const RegWeight &NewWeight) { Weight = NewWeight; }
380 void addWeight(uint32_t Delta) { Weight.addWeight(Delta); } 386 void addWeight(uint32_t Delta) { Weight.addWeight(Delta); }
381 void dump(Ostream &Str) const; 387 void dump(Ostream &Str) const;
382 388
383 private: 389 private:
384 typedef std::pair<InstNumberT, InstNumberT> RangeElementType; 390 typedef std::pair<InstNumberT, InstNumberT> RangeElementType;
385 // RangeType is arena-allocated from the Cfg's allocator. 391 /// RangeType is arena-allocated from the Cfg's allocator.
386 typedef std::vector<RangeElementType, CfgLocalAllocator<RangeElementType>> 392 typedef std::vector<RangeElementType, CfgLocalAllocator<RangeElementType>>
387 RangeType; 393 RangeType;
388 RangeType Range; 394 RangeType Range;
389 RegWeight Weight = RegWeight(0); 395 RegWeight Weight = RegWeight(0);
390 // TrimmedBegin is an optimization for the overlaps() computation. 396 /// TrimmedBegin is an optimization for the overlaps() computation.
391 // Since the linear-scan algorithm always calls it as overlaps(Cur) 397 /// Since the linear-scan algorithm always calls it as overlaps(Cur)
392 // and Cur advances monotonically according to live range start, we 398 /// and Cur advances monotonically according to live range start, we
393 // can optimize overlaps() by ignoring all segments that end before 399 /// can optimize overlaps() by ignoring all segments that end before
394 // the start of Cur's range. The linear-scan code enables this by 400 /// the start of Cur's range. The linear-scan code enables this by
395 // calling trim() on the ranges of interest as Cur advances. Note 401 /// calling trim() on the ranges of interest as Cur advances. Note
396 // that linear-scan also has to initialize TrimmedBegin at the 402 /// that linear-scan also has to initialize TrimmedBegin at the
397 // beginning by calling untrim(). 403 /// beginning by calling untrim().
398 RangeType::const_iterator TrimmedBegin; 404 RangeType::const_iterator TrimmedBegin;
399 }; 405 };
400 406
401 Ostream &operator<<(Ostream &Str, const LiveRange &L); 407 Ostream &operator<<(Ostream &Str, const LiveRange &L);
402 408
403 // Variable represents an operand that is register-allocated or 409 /// Variable represents an operand that is register-allocated or
404 // stack-allocated. If it is register-allocated, it will ultimately 410 /// stack-allocated. If it is register-allocated, it will ultimately
405 // have a non-negative RegNum field. 411 /// have a non-negative RegNum field.
406 class Variable : public Operand { 412 class Variable : public Operand {
407 Variable() = delete; 413 Variable() = delete;
408 Variable(const Variable &) = delete; 414 Variable(const Variable &) = delete;
409 Variable &operator=(const Variable &) = delete; 415 Variable &operator=(const Variable &) = delete;
410 416
411 public: 417 public:
412 static Variable *create(Cfg *Func, Type Ty, SizeT Index) { 418 static Variable *create(Cfg *Func, Type Ty, SizeT Index) {
413 return new (Func->allocate<Variable>()) Variable(kVariable, Ty, Index); 419 return new (Func->allocate<Variable>()) Variable(kVariable, Ty, Index);
414 } 420 }
415 421
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
479 } 485 }
480 486
481 Variable *getLo() const { return LoVar; } 487 Variable *getLo() const { return LoVar; }
482 Variable *getHi() const { return HiVar; } 488 Variable *getHi() const { return HiVar; }
483 void setLoHi(Variable *Lo, Variable *Hi) { 489 void setLoHi(Variable *Lo, Variable *Hi) {
484 assert(LoVar == nullptr); 490 assert(LoVar == nullptr);
485 assert(HiVar == nullptr); 491 assert(HiVar == nullptr);
486 LoVar = Lo; 492 LoVar = Lo;
487 HiVar = Hi; 493 HiVar = Hi;
488 } 494 }
489 // Creates a temporary copy of the variable with a different type. 495 /// Creates a temporary copy of the variable with a different type.
490 // Used primarily for syntactic correctness of textual assembly 496 /// Used primarily for syntactic correctness of textual assembly
491 // emission. Note that only basic information is copied, in 497 /// emission. Note that only basic information is copied, in
492 // particular not IsArgument, IsImplicitArgument, IgnoreLiveness, 498 /// particular not IsArgument, IsImplicitArgument, IgnoreLiveness,
493 // RegNumTmp, Weight, Live, LoVar, HiVar, VarsReal. 499 /// RegNumTmp, Weight, Live, LoVar, HiVar, VarsReal.
494 Variable *asType(Type Ty); 500 Variable *asType(Type Ty);
495 501
496 void emit(const Cfg *Func) const override; 502 void emit(const Cfg *Func) const override;
497 using Operand::dump; 503 using Operand::dump;
498 void dump(const Cfg *Func, Ostream &Str) const override; 504 void dump(const Cfg *Func, Ostream &Str) const override;
499 505
500 static bool classof(const Operand *Operand) { 506 static bool classof(const Operand *Operand) {
501 OperandKind Kind = Operand->getKind(); 507 OperandKind Kind = Operand->getKind();
502 return Kind >= kVariable && Kind <= kVariable_Num; 508 return Kind >= kVariable && Kind <= kVariable_Num;
503 } 509 }
504 510
505 protected: 511 protected:
506 Variable(OperandKind K, Type Ty, SizeT Index) 512 Variable(OperandKind K, Type Ty, SizeT Index)
507 : Operand(K, Ty), Number(Index) { 513 : Operand(K, Ty), Number(Index) {
508 Vars = VarsReal; 514 Vars = VarsReal;
509 Vars[0] = this; 515 Vars[0] = this;
510 NumVars = 1; 516 NumVars = 1;
511 } 517 }
512 // Number is unique across all variables, and is used as a 518 /// Number is unique across all variables, and is used as a
513 // (bit)vector index for liveness analysis. 519 /// (bit)vector index for liveness analysis.
514 const SizeT Number; 520 const SizeT Number;
515 Cfg::IdentifierIndexType NameIndex = Cfg::IdentifierIndexInvalid; 521 Cfg::IdentifierIndexType NameIndex = Cfg::IdentifierIndexInvalid;
516 bool IsArgument = false; 522 bool IsArgument = false;
517 bool IsImplicitArgument = false; 523 bool IsImplicitArgument = false;
518 // IgnoreLiveness means that the variable should be ignored when 524 /// IgnoreLiveness means that the variable should be ignored when
519 // constructing and validating live ranges. This is usually 525 /// constructing and validating live ranges. This is usually
520 // reserved for the stack pointer. 526 /// reserved for the stack pointer.
521 bool IgnoreLiveness = false; 527 bool IgnoreLiveness = false;
522 // StackOffset is the canonical location on stack (only if 528 /// StackOffset is the canonical location on stack (only if
523 // RegNum==NoRegister || IsArgument). 529 /// RegNum==NoRegister || IsArgument).
524 int32_t StackOffset = 0; 530 int32_t StackOffset = 0;
525 // RegNum is the allocated register, or NoRegister if it isn't 531 /// RegNum is the allocated register, or NoRegister if it isn't
526 // register-allocated. 532 /// register-allocated.
527 int32_t RegNum = NoRegister; 533 int32_t RegNum = NoRegister;
528 // RegNumTmp is the tentative assignment during register allocation. 534 /// RegNumTmp is the tentative assignment during register allocation.
529 int32_t RegNumTmp = NoRegister; 535 int32_t RegNumTmp = NoRegister;
530 RegWeight Weight = RegWeight(1); // Register allocation priority 536 RegWeight Weight = RegWeight(1); // Register allocation priority
531 LiveRange Live; 537 LiveRange Live;
532 // LoVar and HiVar are needed for lowering from 64 to 32 bits. When 538 // LoVar and HiVar are needed for lowering from 64 to 32 bits. When
533 // lowering from I64 to I32 on a 32-bit architecture, we split the 539 // lowering from I64 to I32 on a 32-bit architecture, we split the
534 // variable into two machine-size pieces. LoVar is the low-order 540 // variable into two machine-size pieces. LoVar is the low-order
535 // machine-size portion, and HiVar is the remaining high-order 541 // machine-size portion, and HiVar is the remaining high-order
536 // portion. TODO: It's wasteful to penalize all variables on all 542 // portion. TODO: It's wasteful to penalize all variables on all
537 // targets this way; use a sparser representation. It's also 543 // targets this way; use a sparser representation. It's also
538 // wasteful for a 64-bit target. 544 // wasteful for a 64-bit target.
539 Variable *LoVar = nullptr; 545 Variable *LoVar = nullptr;
540 Variable *HiVar = nullptr; 546 Variable *HiVar = nullptr;
541 // VarsReal (and Operand::Vars) are set up such that Vars[0] == 547 /// VarsReal (and Operand::Vars) are set up such that Vars[0] ==
542 // this. 548 /// this.
543 Variable *VarsReal[1]; 549 Variable *VarsReal[1];
544 }; 550 };
545 551
546 enum MetadataKind { 552 enum MetadataKind {
547 VMK_Uses, // Track only uses, not defs 553 VMK_Uses, /// Track only uses, not defs
548 VMK_SingleDefs, // Track uses+defs, but only record single def 554 VMK_SingleDefs, /// Track uses+defs, but only record single def
549 VMK_All // Track uses+defs, including full def list 555 VMK_All /// Track uses+defs, including full def list
550 }; 556 };
551 typedef std::vector<const Inst *, CfgLocalAllocator<const Inst *>> InstDefList; 557 typedef std::vector<const Inst *, CfgLocalAllocator<const Inst *>> InstDefList;
552 558
553 // VariableTracking tracks the metadata for a single variable. It is 559 /// VariableTracking tracks the metadata for a single variable. It is
554 // only meant to be used internally by VariablesMetadata. 560 /// only meant to be used internally by VariablesMetadata.
555 class VariableTracking { 561 class VariableTracking {
556 VariableTracking &operator=(const VariableTracking &) = delete; 562 VariableTracking &operator=(const VariableTracking &) = delete;
557 563
558 public: 564 public:
559 enum MultiDefState { 565 enum MultiDefState {
560 // TODO(stichnot): Consider using just a simple counter. 566 // TODO(stichnot): Consider using just a simple counter.
561 MDS_Unknown, 567 MDS_Unknown,
562 MDS_SingleDef, 568 MDS_SingleDef,
563 MDS_MultiDefSingleBlock, 569 MDS_MultiDefSingleBlock,
564 MDS_MultiDefMultiBlock 570 MDS_MultiDefMultiBlock
(...skipping 10 matching lines...) Expand all
575 void markUse(MetadataKind TrackingKind, const Inst *Instr, 581 void markUse(MetadataKind TrackingKind, const Inst *Instr,
576 const CfgNode *Node, bool IsFromDef, bool IsImplicit); 582 const CfgNode *Node, bool IsFromDef, bool IsImplicit);
577 void markDef(MetadataKind TrackingKind, const Inst *Instr, 583 void markDef(MetadataKind TrackingKind, const Inst *Instr,
578 const CfgNode *Node); 584 const CfgNode *Node);
579 585
580 private: 586 private:
581 MultiDefState MultiDef = MDS_Unknown; 587 MultiDefState MultiDef = MDS_Unknown;
582 MultiBlockState MultiBlock = MBS_Unknown; 588 MultiBlockState MultiBlock = MBS_Unknown;
583 const CfgNode *SingleUseNode = nullptr; 589 const CfgNode *SingleUseNode = nullptr;
584 const CfgNode *SingleDefNode = nullptr; 590 const CfgNode *SingleDefNode = nullptr;
585 // All definitions of the variable are collected here, in increasing 591 /// All definitions of the variable are collected here, in increasing
586 // order of instruction number. 592 /// order of instruction number.
587 InstDefList Definitions; // Only used if Kind==VMK_All 593 InstDefList Definitions; /// Only used if Kind==VMK_All
588 const Inst *FirstOrSingleDefinition = 594 const Inst *FirstOrSingleDefinition =
589 nullptr; // Is a copy of Definitions[0] if Kind==VMK_All 595 nullptr; /// Is a copy of Definitions[0] if Kind==VMK_All
590 }; 596 };
591 597
592 // VariablesMetadata analyzes and summarizes the metadata for the 598 /// VariablesMetadata analyzes and summarizes the metadata for the
593 // complete set of Variables. 599 /// complete set of Variables.
594 class VariablesMetadata { 600 class VariablesMetadata {
595 VariablesMetadata() = delete; 601 VariablesMetadata() = delete;
596 VariablesMetadata(const VariablesMetadata &) = delete; 602 VariablesMetadata(const VariablesMetadata &) = delete;
597 VariablesMetadata &operator=(const VariablesMetadata &) = delete; 603 VariablesMetadata &operator=(const VariablesMetadata &) = delete;
598 604
599 public: 605 public:
600 explicit VariablesMetadata(const Cfg *Func) : Func(Func) {} 606 explicit VariablesMetadata(const Cfg *Func) : Func(Func) {}
601 // Initialize the state by traversing all instructions/variables in 607 /// Initialize the state by traversing all instructions/variables in
602 // the CFG. 608 /// the CFG.
603 void init(MetadataKind TrackingKind); 609 void init(MetadataKind TrackingKind);
604 // Add a single node. This is called by init(), and can be called 610 /// Add a single node. This is called by init(), and can be called
605 // incrementally from elsewhere, e.g. after edge-splitting. 611 /// incrementally from elsewhere, e.g. after edge-splitting.
606 void addNode(CfgNode *Node); 612 void addNode(CfgNode *Node);
607 // Returns whether the given Variable is tracked in this object. It 613 /// Returns whether the given Variable is tracked in this object. It
608 // should only return false if changes were made to the CFG after 614 /// should only return false if changes were made to the CFG after
609 // running init(), in which case the state is stale and the results 615 /// running init(), in which case the state is stale and the results
610 // shouldn't be trusted (but it may be OK e.g. for dumping). 616 /// shouldn't be trusted (but it may be OK e.g. for dumping).
611 bool isTracked(const Variable *Var) const { 617 bool isTracked(const Variable *Var) const {
612 return Var->getIndex() < Metadata.size(); 618 return Var->getIndex() < Metadata.size();
613 } 619 }
614 620
615 // Returns whether the given Variable has multiple definitions. 621 /// Returns whether the given Variable has multiple definitions.
616 bool isMultiDef(const Variable *Var) const; 622 bool isMultiDef(const Variable *Var) const;
617 // Returns the first definition instruction of the given Variable. 623 /// Returns the first definition instruction of the given Variable.
618 // This is only valid for variables whose definitions are all within 624 /// This is only valid for variables whose definitions are all within
619 // the same block, e.g. T after the lowered sequence "T=B; T+=C; 625 /// the same block, e.g. T after the lowered sequence "T=B; T+=C;
620 // A=T", for which getFirstDefinition(T) would return the "T=B" 626 /// A=T", for which getFirstDefinition(T) would return the "T=B"
621 // instruction. For variables with definitions span multiple 627 /// instruction. For variables with definitions span multiple
622 // blocks, nullptr is returned. 628 /// blocks, nullptr is returned.
623 const Inst *getFirstDefinition(const Variable *Var) const; 629 const Inst *getFirstDefinition(const Variable *Var) const;
624 // Returns the definition instruction of the given Variable, when 630 /// Returns the definition instruction of the given Variable, when
625 // the variable has exactly one definition. Otherwise, nullptr is 631 /// the variable has exactly one definition. Otherwise, nullptr is
626 // returned. 632 /// returned.
627 const Inst *getSingleDefinition(const Variable *Var) const; 633 const Inst *getSingleDefinition(const Variable *Var) const;
628 // Returns the list of all definition instructions of the given 634 /// Returns the list of all definition instructions of the given
629 // Variable. 635 /// Variable.
630 const InstDefList &getLatterDefinitions(const Variable *Var) const; 636 const InstDefList &getLatterDefinitions(const Variable *Var) const;
631 637
632 // Returns whether the given Variable is live across multiple 638 /// Returns whether the given Variable is live across multiple
633 // blocks. Mainly, this is used to partition Variables into 639 /// blocks. Mainly, this is used to partition Variables into
634 // single-block versus multi-block sets for leveraging sparsity in 640 /// single-block versus multi-block sets for leveraging sparsity in
635 // liveness analysis, and for implementing simple stack slot 641 /// liveness analysis, and for implementing simple stack slot
636 // coalescing. As a special case, function arguments are always 642 /// coalescing. As a special case, function arguments are always
637 // considered multi-block because they are live coming into the 643 /// considered multi-block because they are live coming into the
638 // entry block. 644 /// entry block.
639 bool isMultiBlock(const Variable *Var) const; 645 bool isMultiBlock(const Variable *Var) const;
640 // Returns the node that the given Variable is used in, assuming 646 /// Returns the node that the given Variable is used in, assuming
641 // isMultiBlock() returns false. Otherwise, nullptr is returned. 647 /// isMultiBlock() returns false. Otherwise, nullptr is returned.
642 const CfgNode *getLocalUseNode(const Variable *Var) const; 648 const CfgNode *getLocalUseNode(const Variable *Var) const;
643 649
644 private: 650 private:
645 const Cfg *Func; 651 const Cfg *Func;
646 MetadataKind Kind; 652 MetadataKind Kind;
647 std::vector<VariableTracking> Metadata; 653 std::vector<VariableTracking> Metadata;
648 const static InstDefList NoDefinitions; 654 const static InstDefList NoDefinitions;
649 }; 655 };
650 656
651 } // end of namespace Ice 657 } // end of namespace Ice
652 658
653 #endif // SUBZERO_SRC_ICEOPERAND_H 659 #endif // SUBZERO_SRC_ICEOPERAND_H
OLDNEW
« no previous file with comments | « src/IceLiveness.cpp ('k') | src/IceOperand.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698