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

Side by Side Diff: src/IceOperand.h

Issue 1341423002: Reflow comments to use the full width. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Fix spelling and rebase Created 5 years, 3 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/IceLoopAnalyzer.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 /// \file 10 /// \file
(...skipping 27 matching lines...) Expand all
38 kConstInteger64, 38 kConstInteger64,
39 kConstFloat, 39 kConstFloat,
40 kConstDouble, 40 kConstDouble,
41 kConstRelocatable, 41 kConstRelocatable,
42 kConstUndef, 42 kConstUndef,
43 kConst_Target, // leave space for target-specific constant kinds 43 kConst_Target, // leave space for target-specific constant kinds
44 kConst_Max = kConst_Target + MaxTargetKinds, 44 kConst_Max = kConst_Target + MaxTargetKinds,
45 kVariable, 45 kVariable,
46 kVariable_Target, // leave space for target-specific variable kinds 46 kVariable_Target, // leave space for target-specific variable kinds
47 kVariable_Max = kVariable_Target + MaxTargetKinds, 47 kVariable_Max = kVariable_Target + MaxTargetKinds,
48 // Target-specific operand classes use kTarget as the starting 48 // Target-specific operand classes use kTarget as the starting point for
49 // point for their Kind enum space. Note that the value-spaces are shared 49 // their Kind enum space. Note that the value-spaces are shared across
50 // across targets. To avoid confusion over the definition of shared 50 // targets. To avoid confusion over the definition of shared values, an
51 // values, an object specific to one target should never be passed 51 // object specific to one target should never be passed to a different
52 // to a different target. 52 // target.
53 kTarget, 53 kTarget,
54 kTarget_Max = std::numeric_limits<uint8_t>::max(), 54 kTarget_Max = std::numeric_limits<uint8_t>::max(),
55 }; 55 };
56 static_assert(kTarget <= kTarget_Max, "Must not be above max."); 56 static_assert(kTarget <= kTarget_Max, "Must not be above max.");
57 OperandKind getKind() const { return Kind; } 57 OperandKind getKind() const { return Kind; }
58 Type getType() const { return Ty; } 58 Type getType() const { return Ty; }
59 59
60 /// Every Operand keeps an array of the Variables referenced in the operand. 60 /// Every Operand keeps an array of the Variables referenced in the operand.
61 /// This is so that the liveness operations can get quick access to the 61 /// This is so that the liveness operations can get quick access to the
62 /// variables of interest, without having to dig so far into the operand. 62 /// variables of interest, without having to dig so far into the operand.
63 SizeT getNumVars() const { return NumVars; } 63 SizeT getNumVars() const { return NumVars; }
64 Variable *getVar(SizeT I) const { 64 Variable *getVar(SizeT I) const {
65 assert(I < getNumVars()); 65 assert(I < getNumVars());
66 return Vars[I]; 66 return Vars[I];
67 } 67 }
68 virtual void emit(const Cfg *Func) const = 0; 68 virtual void emit(const Cfg *Func) const = 0;
69 69
70 /// \name Dumping functions. 70 /// \name Dumping functions.
71 /// @{ 71 /// @{
72 72
73 /// The dump(Func,Str) implementation must be sure to handle the 73 /// The dump(Func,Str) implementation must be sure to handle the situation
74 /// situation where Func==nullptr. 74 /// where Func==nullptr.
75 virtual void dump(const Cfg *Func, Ostream &Str) const = 0; 75 virtual void dump(const Cfg *Func, Ostream &Str) const = 0;
76 void dump(const Cfg *Func) const { 76 void dump(const Cfg *Func) const {
77 if (!BuildDefs::dump()) 77 if (!BuildDefs::dump())
78 return; 78 return;
79 assert(Func); 79 assert(Func);
80 dump(Func, Func->getContext()->getStrDump()); 80 dump(Func, Func->getContext()->getStrDump());
81 } 81 }
82 void dump(Ostream &Str) const { 82 void dump(Ostream &Str) const {
83 if (BuildDefs::dump()) 83 if (BuildDefs::dump())
84 dump(nullptr, Str); 84 dump(nullptr, Str);
(...skipping 13 matching lines...) Expand all
98 SizeT NumVars = 0; 98 SizeT NumVars = 0;
99 Variable **Vars = nullptr; 99 Variable **Vars = nullptr;
100 }; 100 };
101 101
102 template <class StreamType> 102 template <class StreamType>
103 inline StreamType &operator<<(StreamType &Str, const Operand &Op) { 103 inline StreamType &operator<<(StreamType &Str, const Operand &Op) {
104 Op.dump(Str); 104 Op.dump(Str);
105 return Str; 105 return Str;
106 } 106 }
107 107
108 /// Constant is the abstract base class for constants. All 108 /// Constant is the abstract base class for constants. All constants are
109 /// constants are allocated from a global arena and are pooled. 109 /// allocated from a global arena and are pooled.
110 class Constant : public Operand { 110 class Constant : public Operand {
111 Constant() = delete; 111 Constant() = delete;
112 Constant(const Constant &) = delete; 112 Constant(const Constant &) = delete;
113 Constant &operator=(const Constant &) = delete; 113 Constant &operator=(const Constant &) = delete;
114 114
115 public: 115 public:
116 void emitPoolLabel(Ostream &Str) const { 116 void emitPoolLabel(Ostream &Str) const {
117 Str << ".L$" << getType() << "$" << PoolEntryID; 117 Str << ".L$" << getType() << "$" << PoolEntryID;
118 } 118 }
119 void emit(const Cfg *Func) const override { emit(Func->getTarget()); } 119 void emit(const Cfg *Func) const override { emit(Func->getTarget()); }
120 virtual void emit(TargetLowering *Target) const = 0; 120 virtual void emit(TargetLowering *Target) const = 0;
121 121
122 static bool classof(const Operand *Operand) { 122 static bool classof(const Operand *Operand) {
123 OperandKind Kind = Operand->getKind(); 123 OperandKind Kind = Operand->getKind();
124 return Kind >= kConst_Base && Kind <= kConst_Max; 124 return Kind >= kConst_Base && Kind <= kConst_Max;
125 } 125 }
126 126
127 /// Judge if this given immediate should be randomized or pooled 127 /// Judge if this given immediate should be randomized or pooled By default
128 /// By default should return false, only constant integers should 128 /// should return false, only constant integers should truly go through this
129 /// truly go through this method. 129 /// method.
130 virtual bool shouldBeRandomizedOrPooled(const GlobalContext *Ctx) { 130 virtual bool shouldBeRandomizedOrPooled(const GlobalContext *Ctx) {
131 (void)Ctx; 131 (void)Ctx;
132 return false; 132 return false;
133 } 133 }
134 134
135 void setShouldBePooled(bool R) { shouldBePooled = R; } 135 void setShouldBePooled(bool R) { shouldBePooled = R; }
136 136
137 bool getShouldBePooled() const { return shouldBePooled; } 137 bool getShouldBePooled() const { return shouldBePooled; }
138 138
139 protected: 139 protected:
140 Constant(OperandKind Kind, Type Ty, uint32_t PoolEntryID) 140 Constant(OperandKind Kind, Type Ty, uint32_t PoolEntryID)
141 : Operand(Kind, Ty), PoolEntryID(PoolEntryID), shouldBePooled(false) { 141 : Operand(Kind, Ty), PoolEntryID(PoolEntryID), shouldBePooled(false) {
142 Vars = nullptr; 142 Vars = nullptr;
143 NumVars = 0; 143 NumVars = 0;
144 } 144 }
145 /// PoolEntryID is an integer that uniquely identifies the constant 145 /// PoolEntryID is an integer that uniquely identifies the constant within its
146 /// within its constant pool. It is used for building the constant 146 /// constant pool. It is used for building the constant pool in the object
147 /// pool in the object code and for referencing its entries. 147 /// code and for referencing its entries.
148 const uint32_t PoolEntryID; 148 const uint32_t PoolEntryID;
149 /// Whether we should pool this constant. Usually Float/Double and pooled 149 /// Whether we should pool this constant. Usually Float/Double and pooled
150 /// Integers should be flagged true. 150 /// Integers should be flagged true.
151 bool shouldBePooled; 151 bool shouldBePooled;
152 }; 152 };
153 153
154 /// ConstantPrimitive<> wraps a primitive type. 154 /// ConstantPrimitive<> wraps a primitive type.
155 template <typename T, Operand::OperandKind K> 155 template <typename T, Operand::OperandKind K>
156 class ConstantPrimitive : public Constant { 156 class ConstantPrimitive : public Constant {
157 ConstantPrimitive() = delete; 157 ConstantPrimitive() = delete;
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 bool ConstantInteger32::shouldBeRandomizedOrPooled(const GlobalContext *Ctx); 212 bool ConstantInteger32::shouldBeRandomizedOrPooled(const GlobalContext *Ctx);
213 213
214 template <> 214 template <>
215 inline void ConstantInteger64::dump(const Cfg *, Ostream &Str) const { 215 inline void ConstantInteger64::dump(const Cfg *, Ostream &Str) const {
216 if (!BuildDefs::dump()) 216 if (!BuildDefs::dump())
217 return; 217 return;
218 assert(getType() == IceType_i64); 218 assert(getType() == IceType_i64);
219 Str << static_cast<int64_t>(getValue()); 219 Str << static_cast<int64_t>(getValue());
220 } 220 }
221 221
222 /// RelocatableTuple bundles the parameters that are used to 222 /// RelocatableTuple bundles the parameters that are used to construct an
223 /// construct an ConstantRelocatable. It is done this way so that 223 /// ConstantRelocatable. It is done this way so that ConstantRelocatable can fit
224 /// ConstantRelocatable can fit into the global constant pool 224 /// into the global constant pool template mechanism.
225 /// template mechanism.
226 class RelocatableTuple { 225 class RelocatableTuple {
227 RelocatableTuple() = delete; 226 RelocatableTuple() = delete;
228 RelocatableTuple &operator=(const RelocatableTuple &) = delete; 227 RelocatableTuple &operator=(const RelocatableTuple &) = delete;
229 228
230 public: 229 public:
231 RelocatableTuple(const RelocOffsetT Offset, const IceString &Name, 230 RelocatableTuple(const RelocOffsetT Offset, const IceString &Name,
232 bool SuppressMangling) 231 bool SuppressMangling)
233 : Offset(Offset), Name(Name), SuppressMangling(SuppressMangling) {} 232 : Offset(Offset), Name(Name), SuppressMangling(SuppressMangling) {}
234 RelocatableTuple(const RelocatableTuple &) = default; 233 RelocatableTuple(const RelocatableTuple &) = default;
235 234
236 const RelocOffsetT Offset; 235 const RelocOffsetT Offset;
237 const IceString Name; 236 const IceString Name;
238 bool SuppressMangling; 237 bool SuppressMangling;
239 }; 238 };
240 239
241 bool operator==(const RelocatableTuple &A, const RelocatableTuple &B); 240 bool operator==(const RelocatableTuple &A, const RelocatableTuple &B);
242 241
243 /// ConstantRelocatable represents a symbolic constant combined with 242 /// ConstantRelocatable represents a symbolic constant combined with a fixed
244 /// a fixed offset. 243 /// offset.
245 class ConstantRelocatable : public Constant { 244 class ConstantRelocatable : public Constant {
246 ConstantRelocatable() = delete; 245 ConstantRelocatable() = delete;
247 ConstantRelocatable(const ConstantRelocatable &) = delete; 246 ConstantRelocatable(const ConstantRelocatable &) = delete;
248 ConstantRelocatable &operator=(const ConstantRelocatable &) = delete; 247 ConstantRelocatable &operator=(const ConstantRelocatable &) = delete;
249 248
250 public: 249 public:
251 static ConstantRelocatable *create(GlobalContext *Ctx, Type Ty, 250 static ConstantRelocatable *create(GlobalContext *Ctx, Type Ty,
252 const RelocatableTuple &Tuple, 251 const RelocatableTuple &Tuple,
253 uint32_t PoolEntryID) { 252 uint32_t PoolEntryID) {
254 assert(!Ctx->isIRGenerationDisabled() && 253 assert(!Ctx->isIRGenerationDisabled() &&
(...skipping 20 matching lines...) Expand all
275 private: 274 private:
276 ConstantRelocatable(Type Ty, RelocOffsetT Offset, const IceString &Name, 275 ConstantRelocatable(Type Ty, RelocOffsetT Offset, const IceString &Name,
277 bool SuppressMangling, uint32_t PoolEntryID) 276 bool SuppressMangling, uint32_t PoolEntryID)
278 : Constant(kConstRelocatable, Ty, PoolEntryID), Offset(Offset), 277 : Constant(kConstRelocatable, Ty, PoolEntryID), Offset(Offset),
279 Name(Name), SuppressMangling(SuppressMangling) {} 278 Name(Name), SuppressMangling(SuppressMangling) {}
280 const RelocOffsetT Offset; /// fixed offset to add 279 const RelocOffsetT Offset; /// fixed offset to add
281 const IceString Name; /// optional for debug/dump 280 const IceString Name; /// optional for debug/dump
282 bool SuppressMangling; 281 bool SuppressMangling;
283 }; 282 };
284 283
285 /// ConstantUndef represents an unspecified bit pattern. Although it is 284 /// ConstantUndef represents an unspecified bit pattern. Although it is legal to
286 /// legal to lower ConstantUndef to any value, backends should try to 285 /// lower ConstantUndef to any value, backends should try to make code
287 /// make code generation deterministic by lowering ConstantUndefs to 0. 286 /// generation deterministic by lowering ConstantUndefs to 0.
288 class ConstantUndef : public Constant { 287 class ConstantUndef : public Constant {
289 ConstantUndef() = delete; 288 ConstantUndef() = delete;
290 ConstantUndef(const ConstantUndef &) = delete; 289 ConstantUndef(const ConstantUndef &) = delete;
291 ConstantUndef &operator=(const ConstantUndef &) = delete; 290 ConstantUndef &operator=(const ConstantUndef &) = delete;
292 291
293 public: 292 public:
294 static ConstantUndef *create(GlobalContext *Ctx, Type Ty, 293 static ConstantUndef *create(GlobalContext *Ctx, Type Ty,
295 uint32_t PoolEntryID) { 294 uint32_t PoolEntryID) {
296 assert(!Ctx->isIRGenerationDisabled() && 295 assert(!Ctx->isIRGenerationDisabled() &&
297 "Attempt to build undefined constant when IR generation disabled"); 296 "Attempt to build undefined constant when IR generation disabled");
(...skipping 10 matching lines...) Expand all
308 307
309 static bool classof(const Operand *Operand) { 308 static bool classof(const Operand *Operand) {
310 return Operand->getKind() == kConstUndef; 309 return Operand->getKind() == kConstUndef;
311 } 310 }
312 311
313 private: 312 private:
314 ConstantUndef(Type Ty, uint32_t PoolEntryID) 313 ConstantUndef(Type Ty, uint32_t PoolEntryID)
315 : Constant(kConstUndef, Ty, PoolEntryID) {} 314 : Constant(kConstUndef, Ty, PoolEntryID) {}
316 }; 315 };
317 316
318 /// RegWeight is a wrapper for a uint32_t weight value, with a 317 /// RegWeight is a wrapper for a uint32_t weight value, with a special value
319 /// special value that represents infinite weight, and an addWeight() 318 /// that represents infinite weight, and an addWeight() method that ensures that
320 /// method that ensures that W+infinity=infinity. 319 /// W+infinity=infinity.
321 class RegWeight { 320 class RegWeight {
322 public: 321 public:
323 RegWeight() = default; 322 RegWeight() = default;
324 explicit RegWeight(uint32_t Weight) : Weight(Weight) {} 323 explicit RegWeight(uint32_t Weight) : Weight(Weight) {}
325 RegWeight(const RegWeight &) = default; 324 RegWeight(const RegWeight &) = default;
326 RegWeight &operator=(const RegWeight &) = default; 325 RegWeight &operator=(const RegWeight &) = default;
327 const static uint32_t Inf = ~0; /// Force regalloc to give a register 326 const static uint32_t Inf = ~0; /// Force regalloc to give a register
328 const static uint32_t Zero = 0; /// Force regalloc NOT to give a register 327 const static uint32_t Zero = 0; /// Force regalloc NOT to give a register
329 const static uint32_t Max = Inf - 1; /// Max natural weight. 328 const static uint32_t Max = Inf - 1; /// Max natural weight.
330 void addWeight(uint32_t Delta) { 329 void addWeight(uint32_t Delta) {
331 if (Delta == Inf) 330 if (Delta == Inf)
332 Weight = Inf; 331 Weight = Inf;
333 else if (Weight != Inf) 332 else if (Weight != Inf)
334 if (Utils::add_overflow(Weight, Delta, &Weight) || Weight == Inf) 333 if (Utils::add_overflow(Weight, Delta, &Weight) || Weight == Inf)
335 Weight = Max; 334 Weight = Max;
336 } 335 }
337 void addWeight(const RegWeight &Other) { addWeight(Other.Weight); } 336 void addWeight(const RegWeight &Other) { addWeight(Other.Weight); }
338 void setWeight(uint32_t Val) { Weight = Val; } 337 void setWeight(uint32_t Val) { Weight = Val; }
339 uint32_t getWeight() const { return Weight; } 338 uint32_t getWeight() const { return Weight; }
340 339
341 private: 340 private:
342 uint32_t Weight = 0; 341 uint32_t Weight = 0;
343 }; 342 };
344 Ostream &operator<<(Ostream &Str, const RegWeight &W); 343 Ostream &operator<<(Ostream &Str, const RegWeight &W);
345 bool operator<(const RegWeight &A, const RegWeight &B); 344 bool operator<(const RegWeight &A, const RegWeight &B);
346 bool operator<=(const RegWeight &A, const RegWeight &B); 345 bool operator<=(const RegWeight &A, const RegWeight &B);
347 bool operator==(const RegWeight &A, const RegWeight &B); 346 bool operator==(const RegWeight &A, const RegWeight &B);
348 347
349 /// LiveRange is a set of instruction number intervals representing 348 /// LiveRange is a set of instruction number intervals representing a variable's
350 /// a variable's live range. Generally there is one interval per basic 349 /// live range. Generally there is one interval per basic block where the
351 /// block where the variable is live, but adjacent intervals get 350 /// variable is live, but adjacent intervals get coalesced into a single
352 /// coalesced into a single interval. 351 /// interval.
353 class LiveRange { 352 class LiveRange {
354 public: 353 public:
355 LiveRange() = default; 354 LiveRange() = default;
356 /// Special constructor for building a kill set. The advantage is 355 /// Special constructor for building a kill set. The advantage is that we can
357 /// that we can reserve the right amount of space in advance. 356 /// reserve the right amount of space in advance.
358 explicit LiveRange(const std::vector<InstNumberT> &Kills) { 357 explicit LiveRange(const std::vector<InstNumberT> &Kills) {
359 Range.reserve(Kills.size()); 358 Range.reserve(Kills.size());
360 for (InstNumberT I : Kills) 359 for (InstNumberT I : Kills)
361 addSegment(I, I); 360 addSegment(I, I);
362 } 361 }
363 LiveRange(const LiveRange &) = default; 362 LiveRange(const LiveRange &) = default;
364 LiveRange &operator=(const LiveRange &) = default; 363 LiveRange &operator=(const LiveRange &) = default;
365 364
366 void reset() { 365 void reset() {
367 Range.clear(); 366 Range.clear();
(...skipping 17 matching lines...) Expand all
385 void trim(InstNumberT Lower); 384 void trim(InstNumberT Lower);
386 385
387 void dump(Ostream &Str) const; 386 void dump(Ostream &Str) const;
388 387
389 private: 388 private:
390 using RangeElementType = std::pair<InstNumberT, InstNumberT>; 389 using RangeElementType = std::pair<InstNumberT, InstNumberT>;
391 /// RangeType is arena-allocated from the Cfg's allocator. 390 /// RangeType is arena-allocated from the Cfg's allocator.
392 using RangeType = 391 using RangeType =
393 std::vector<RangeElementType, CfgLocalAllocator<RangeElementType>>; 392 std::vector<RangeElementType, CfgLocalAllocator<RangeElementType>>;
394 RangeType Range; 393 RangeType Range;
395 /// TrimmedBegin is an optimization for the overlaps() computation. 394 /// TrimmedBegin is an optimization for the overlaps() computation. Since the
396 /// Since the linear-scan algorithm always calls it as overlaps(Cur) 395 /// linear-scan algorithm always calls it as overlaps(Cur) and Cur advances
397 /// and Cur advances monotonically according to live range start, we 396 /// monotonically according to live range start, we can optimize overlaps() by
398 /// can optimize overlaps() by ignoring all segments that end before 397 /// ignoring all segments that end before the start of Cur's range. The
399 /// the start of Cur's range. The linear-scan code enables this by 398 /// linear-scan code enables this by calling trim() on the ranges of interest
400 /// calling trim() on the ranges of interest as Cur advances. Note 399 /// as Cur advances. Note that linear-scan also has to initialize TrimmedBegin
401 /// that linear-scan also has to initialize TrimmedBegin at the 400 /// at the beginning by calling untrim().
402 /// beginning by calling untrim().
403 RangeType::const_iterator TrimmedBegin; 401 RangeType::const_iterator TrimmedBegin;
404 }; 402 };
405 403
406 Ostream &operator<<(Ostream &Str, const LiveRange &L); 404 Ostream &operator<<(Ostream &Str, const LiveRange &L);
407 405
408 /// Variable represents an operand that is register-allocated or 406 /// Variable represents an operand that is register-allocated or
409 /// stack-allocated. If it is register-allocated, it will ultimately 407 /// stack-allocated. If it is register-allocated, it will ultimately have a
410 /// have a non-negative RegNum field. 408 /// non-negative RegNum field.
411 class Variable : public Operand { 409 class Variable : public Operand {
412 Variable() = delete; 410 Variable() = delete;
413 Variable(const Variable &) = delete; 411 Variable(const Variable &) = delete;
414 Variable &operator=(const Variable &) = delete; 412 Variable &operator=(const Variable &) = delete;
415 413
416 enum RegRequirement { 414 enum RegRequirement {
417 RR_MayHaveRegister, 415 RR_MayHaveRegister,
418 RR_MustHaveRegister, 416 RR_MustHaveRegister,
419 RR_MustNotHaveRegister, 417 RR_MustNotHaveRegister,
420 }; 418 };
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
488 } 486 }
489 487
490 Variable *getLo() const { return LoVar; } 488 Variable *getLo() const { return LoVar; }
491 Variable *getHi() const { return HiVar; } 489 Variable *getHi() const { return HiVar; }
492 void setLoHi(Variable *Lo, Variable *Hi) { 490 void setLoHi(Variable *Lo, Variable *Hi) {
493 assert(LoVar == nullptr); 491 assert(LoVar == nullptr);
494 assert(HiVar == nullptr); 492 assert(HiVar == nullptr);
495 LoVar = Lo; 493 LoVar = Lo;
496 HiVar = Hi; 494 HiVar = Hi;
497 } 495 }
498 /// Creates a temporary copy of the variable with a different type. 496 /// Creates a temporary copy of the variable with a different type. Used
499 /// Used primarily for syntactic correctness of textual assembly 497 /// primarily for syntactic correctness of textual assembly emission. Note
500 /// emission. Note that only basic information is copied, in 498 /// that only basic information is copied, in particular not IsArgument,
501 /// particular not IsArgument, IsImplicitArgument, IgnoreLiveness, 499 /// IsImplicitArgument, IgnoreLiveness, RegNumTmp, Live, LoVar, HiVar,
502 /// RegNumTmp, Live, LoVar, HiVar, VarsReal. 500 /// VarsReal.
503 Variable *asType(Type Ty); 501 Variable *asType(Type Ty);
504 502
505 void emit(const Cfg *Func) const override; 503 void emit(const Cfg *Func) const override;
506 using Operand::dump; 504 using Operand::dump;
507 void dump(const Cfg *Func, Ostream &Str) const override; 505 void dump(const Cfg *Func, Ostream &Str) const override;
508 506
509 /// Return reg num of base register, if different from stack/frame register. 507 /// Return reg num of base register, if different from stack/frame register.
510 virtual int32_t getBaseRegNum() const { return NoRegister; } 508 virtual int32_t getBaseRegNum() const { return NoRegister; }
511 509
512 static bool classof(const Operand *Operand) { 510 static bool classof(const Operand *Operand) {
513 OperandKind Kind = Operand->getKind(); 511 OperandKind Kind = Operand->getKind();
514 return Kind >= kVariable && Kind <= kVariable_Max; 512 return Kind >= kVariable && Kind <= kVariable_Max;
515 } 513 }
516 514
517 protected: 515 protected:
518 Variable(OperandKind K, Type Ty, SizeT Index) 516 Variable(OperandKind K, Type Ty, SizeT Index)
519 : Operand(K, Ty), Number(Index) { 517 : Operand(K, Ty), Number(Index) {
520 Vars = VarsReal; 518 Vars = VarsReal;
521 Vars[0] = this; 519 Vars[0] = this;
522 NumVars = 1; 520 NumVars = 1;
523 } 521 }
524 /// Number is unique across all variables, and is used as a 522 /// Number is unique across all variables, and is used as a (bit)vector index
525 /// (bit)vector index for liveness analysis. 523 /// for liveness analysis.
526 const SizeT Number; 524 const SizeT Number;
527 Cfg::IdentifierIndexType NameIndex = Cfg::IdentifierIndexInvalid; 525 Cfg::IdentifierIndexType NameIndex = Cfg::IdentifierIndexInvalid;
528 bool IsArgument = false; 526 bool IsArgument = false;
529 bool IsImplicitArgument = false; 527 bool IsImplicitArgument = false;
530 /// IgnoreLiveness means that the variable should be ignored when 528 /// IgnoreLiveness means that the variable should be ignored when constructing
531 /// constructing and validating live ranges. This is usually 529 /// and validating live ranges. This is usually reserved for the stack
532 /// reserved for the stack pointer. 530 /// pointer.
533 bool IgnoreLiveness = false; 531 bool IgnoreLiveness = false;
534 /// StackOffset is the canonical location on stack (only if 532 /// StackOffset is the canonical location on stack (only if RegNum==NoRegister
535 /// RegNum==NoRegister || IsArgument). 533 /// || IsArgument).
536 int32_t StackOffset = 0; 534 int32_t StackOffset = 0;
537 /// RegNum is the allocated register, or NoRegister if it isn't 535 /// RegNum is the allocated register, or NoRegister if it isn't
538 /// register-allocated. 536 /// register-allocated.
539 int32_t RegNum = NoRegister; 537 int32_t RegNum = NoRegister;
540 /// RegNumTmp is the tentative assignment during register allocation. 538 /// RegNumTmp is the tentative assignment during register allocation.
541 int32_t RegNumTmp = NoRegister; 539 int32_t RegNumTmp = NoRegister;
542 RegRequirement RegRequirement = RR_MayHaveRegister; 540 RegRequirement RegRequirement = RR_MayHaveRegister;
543 LiveRange Live; 541 LiveRange Live;
544 // LoVar and HiVar are needed for lowering from 64 to 32 bits. When 542 // LoVar and HiVar are needed for lowering from 64 to 32 bits. When lowering
545 // lowering from I64 to I32 on a 32-bit architecture, we split the 543 // from I64 to I32 on a 32-bit architecture, we split the variable into two
546 // variable into two machine-size pieces. LoVar is the low-order 544 // machine-size pieces. LoVar is the low-order machine-size portion, and
547 // machine-size portion, and HiVar is the remaining high-order 545 // HiVar is the remaining high-order portion.
548 // portion. TODO: It's wasteful to penalize all variables on all 546 // TODO: It's wasteful to penalize all variables on all targets this way; use
549 // targets this way; use a sparser representation. It's also 547 // a sparser representation. It's also wasteful for a 64-bit target.
550 // wasteful for a 64-bit target.
551 Variable *LoVar = nullptr; 548 Variable *LoVar = nullptr;
552 Variable *HiVar = nullptr; 549 Variable *HiVar = nullptr;
553 /// VarsReal (and Operand::Vars) are set up such that Vars[0] == 550 /// VarsReal (and Operand::Vars) are set up such that Vars[0] == this.
554 /// this.
555 Variable *VarsReal[1]; 551 Variable *VarsReal[1];
556 }; 552 };
557 553
558 enum MetadataKind { 554 enum MetadataKind {
559 VMK_Uses, /// Track only uses, not defs 555 VMK_Uses, /// Track only uses, not defs
560 VMK_SingleDefs, /// Track uses+defs, but only record single def 556 VMK_SingleDefs, /// Track uses+defs, but only record single def
561 VMK_All /// Track uses+defs, including full def list 557 VMK_All /// Track uses+defs, including full def list
562 }; 558 };
563 using InstDefList = std::vector<const Inst *, CfgLocalAllocator<const Inst *>>; 559 using InstDefList = std::vector<const Inst *, CfgLocalAllocator<const Inst *>>;
564 560
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
604 600
605 /// VariablesMetadata analyzes and summarizes the metadata for the complete set 601 /// VariablesMetadata analyzes and summarizes the metadata for the complete set
606 /// of Variables. 602 /// of Variables.
607 class VariablesMetadata { 603 class VariablesMetadata {
608 VariablesMetadata() = delete; 604 VariablesMetadata() = delete;
609 VariablesMetadata(const VariablesMetadata &) = delete; 605 VariablesMetadata(const VariablesMetadata &) = delete;
610 VariablesMetadata &operator=(const VariablesMetadata &) = delete; 606 VariablesMetadata &operator=(const VariablesMetadata &) = delete;
611 607
612 public: 608 public:
613 explicit VariablesMetadata(const Cfg *Func) : Func(Func) {} 609 explicit VariablesMetadata(const Cfg *Func) : Func(Func) {}
614 /// Initialize the state by traversing all instructions/variables in 610 /// Initialize the state by traversing all instructions/variables in the CFG.
615 /// the CFG.
616 void init(MetadataKind TrackingKind); 611 void init(MetadataKind TrackingKind);
617 /// Add a single node. This is called by init(), and can be called 612 /// Add a single node. This is called by init(), and can be called
618 /// incrementally from elsewhere, e.g. after edge-splitting. 613 /// incrementally from elsewhere, e.g. after edge-splitting.
619 void addNode(CfgNode *Node); 614 void addNode(CfgNode *Node);
620 /// Returns whether the given Variable is tracked in this object. It should 615 /// Returns whether the given Variable is tracked in this object. It should
621 /// only return false if changes were made to the CFG after running init(), in 616 /// only return false if changes were made to the CFG after running init(), in
622 /// which case the state is stale and the results shouldn't be trusted (but it 617 /// which case the state is stale and the results shouldn't be trusted (but it
623 /// may be OK e.g. for dumping). 618 /// may be OK e.g. for dumping).
624 bool isTracked(const Variable *Var) const { 619 bool isTracked(const Variable *Var) const {
625 return Var->getIndex() < Metadata.size(); 620 return Var->getIndex() < Metadata.size();
626 } 621 }
627 622
628 /// Returns whether the given Variable has multiple definitions. 623 /// Returns whether the given Variable has multiple definitions.
629 bool isMultiDef(const Variable *Var) const; 624 bool isMultiDef(const Variable *Var) const;
630 /// Returns the first definition instruction of the given Variable. This is 625 /// Returns the first definition instruction of the given Variable. This is
631 /// only valid for variables whose definitions are all within the same block, 626 /// only valid for variables whose definitions are all within the same block,
632 /// e.g. T after the lowered sequence "T=B; T+=C; A=T", for which 627 /// e.g. T after the lowered sequence "T=B; T+=C; A=T", for which
633 /// getFirstDefinition(T) would return the "T=B" instruction. For variables 628 /// getFirstDefinition(T) would return the "T=B" instruction. For variables
634 /// with definitions span multiple blocks, nullptr is returned. 629 /// with definitions span multiple blocks, nullptr is returned.
635 const Inst *getFirstDefinition(const Variable *Var) const; 630 const Inst *getFirstDefinition(const Variable *Var) const;
636 /// Returns the definition instruction of the given Variable, when 631 /// Returns the definition instruction of the given Variable, when the
637 /// the variable has exactly one definition. Otherwise, nullptr is 632 /// variable has exactly one definition. Otherwise, nullptr is returned.
638 /// returned.
639 const Inst *getSingleDefinition(const Variable *Var) const; 633 const Inst *getSingleDefinition(const Variable *Var) const;
640 /// Returns the list of all definition instructions of the given Variable. 634 /// Returns the list of all definition instructions of the given Variable.
641 const InstDefList &getLatterDefinitions(const Variable *Var) const; 635 const InstDefList &getLatterDefinitions(const Variable *Var) const;
642 636
643 /// Returns whether the given Variable is live across multiple 637 /// Returns whether the given Variable is live across multiple blocks. Mainly,
644 /// blocks. Mainly, this is used to partition Variables into 638 /// this is used to partition Variables into single-block versus multi-block
645 /// single-block versus multi-block sets for leveraging sparsity in 639 /// sets for leveraging sparsity in liveness analysis, and for implementing
646 /// liveness analysis, and for implementing simple stack slot 640 /// simple stack slot coalescing. As a special case, function arguments are
647 /// coalescing. As a special case, function arguments are always 641 /// always considered multi-block because they are live coming into the entry
648 /// considered multi-block because they are live coming into the 642 /// block.
649 /// entry block.
650 bool isMultiBlock(const Variable *Var) const; 643 bool isMultiBlock(const Variable *Var) const;
651 /// Returns the node that the given Variable is used in, assuming 644 /// Returns the node that the given Variable is used in, assuming
652 /// isMultiBlock() returns false. Otherwise, nullptr is returned. 645 /// isMultiBlock() returns false. Otherwise, nullptr is returned.
653 CfgNode *getLocalUseNode(const Variable *Var) const; 646 CfgNode *getLocalUseNode(const Variable *Var) const;
654 647
655 /// Returns the total use weight computed as the sum of uses multiplied by a 648 /// Returns the total use weight computed as the sum of uses multiplied by a
656 /// loop nest depth factor for each use. 649 /// loop nest depth factor for each use.
657 RegWeight getUseWeight(const Variable *Var) const; 650 RegWeight getUseWeight(const Variable *Var) const;
658 651
659 private: 652 private:
660 const Cfg *Func; 653 const Cfg *Func;
661 MetadataKind Kind; 654 MetadataKind Kind;
662 std::vector<VariableTracking> Metadata; 655 std::vector<VariableTracking> Metadata;
663 const static InstDefList NoDefinitions; 656 const static InstDefList NoDefinitions;
664 }; 657 };
665 658
666 } // end of namespace Ice 659 } // end of namespace Ice
667 660
668 #endif // SUBZERO_SRC_ICEOPERAND_H 661 #endif // SUBZERO_SRC_ICEOPERAND_H
OLDNEW
« no previous file with comments | « src/IceLoopAnalyzer.cpp ('k') | src/IceOperand.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698