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

Side by Side Diff: src/IceOperand.h

Issue 300563003: Subzero: Initial O2 lowering (Closed) Base URL: https://gerrit.chromium.org/gerrit/p/native_client/pnacl-subzero.git@master
Patch Set: Jan's third-round comments Created 6 years, 6 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 // This file declares the Operand class and its target-independent
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 private: 74 private:
75 Operand(const Operand &) LLVM_DELETED_FUNCTION; 75 Operand(const Operand &) LLVM_DELETED_FUNCTION;
76 Operand &operator=(const Operand &) LLVM_DELETED_FUNCTION; 76 Operand &operator=(const Operand &) LLVM_DELETED_FUNCTION;
77 }; 77 };
78 78
79 // Constant is the abstract base class for constants. All 79 // Constant is the abstract base class for constants. All
80 // constants are allocated from a global arena and are pooled. 80 // constants are allocated from a global arena and are pooled.
81 class Constant : public Operand { 81 class Constant : public Operand {
82 public: 82 public:
83 uint32_t getPoolEntryID() const { return PoolEntryID; } 83 uint32_t getPoolEntryID() const { return PoolEntryID; }
84 virtual void emit(const Cfg *Func) const = 0; 84 virtual void emit(const Cfg *Func) const { emit(Func->getContext()); }
85 virtual void dump(const Cfg *Func) const = 0; 85 virtual void dump(const Cfg *Func) const { dump(Func->getContext()); }
86 virtual void emit(GlobalContext *Ctx) const = 0;
87 virtual void dump(GlobalContext *Ctx) const = 0;
86 88
87 static bool classof(const Operand *Operand) { 89 static bool classof(const Operand *Operand) {
88 OperandKind Kind = Operand->getKind(); 90 OperandKind Kind = Operand->getKind();
89 return Kind >= kConst_Base && Kind <= kConst_Num; 91 return Kind >= kConst_Base && Kind <= kConst_Num;
90 } 92 }
91 93
92 protected: 94 protected:
93 Constant(OperandKind Kind, Type Ty, uint32_t PoolEntryID) 95 Constant(OperandKind Kind, Type Ty, uint32_t PoolEntryID)
94 : Operand(Kind, Ty), PoolEntryID(PoolEntryID) { 96 : Operand(Kind, Ty), PoolEntryID(PoolEntryID) {
95 Vars = NULL; 97 Vars = NULL;
(...skipping 13 matching lines...) Expand all
109 // ConstantPrimitive<> wraps a primitive type. 111 // ConstantPrimitive<> wraps a primitive type.
110 template <typename T, Operand::OperandKind K> 112 template <typename T, Operand::OperandKind K>
111 class ConstantPrimitive : public Constant { 113 class ConstantPrimitive : public Constant {
112 public: 114 public:
113 static ConstantPrimitive *create(GlobalContext *Ctx, Type Ty, T Value, 115 static ConstantPrimitive *create(GlobalContext *Ctx, Type Ty, T Value,
114 uint32_t PoolEntryID) { 116 uint32_t PoolEntryID) {
115 return new (Ctx->allocate<ConstantPrimitive>()) 117 return new (Ctx->allocate<ConstantPrimitive>())
116 ConstantPrimitive(Ty, Value, PoolEntryID); 118 ConstantPrimitive(Ty, Value, PoolEntryID);
117 } 119 }
118 T getValue() const { return Value; } 120 T getValue() const { return Value; }
119 virtual void emit(const Cfg *Func) const { 121 using Constant::emit;
120 Ostream &Str = Func->getContext()->getStrEmit(); 122 virtual void emit(GlobalContext *Ctx) const {
123 Ostream &Str = Ctx->getStrEmit();
121 Str << getValue(); 124 Str << getValue();
122 } 125 }
123 virtual void dump(const Cfg *Func) const { 126 using Constant::dump;
124 Ostream &Str = Func->getContext()->getStrDump(); 127 virtual void dump(GlobalContext *Ctx) const {
128 Ostream &Str = Ctx->getStrDump();
125 Str << getValue(); 129 Str << getValue();
126 } 130 }
127 131
128 static bool classof(const Operand *Operand) { 132 static bool classof(const Operand *Operand) {
129 return Operand->getKind() == K; 133 return Operand->getKind() == K;
130 } 134 }
131 135
132 private: 136 private:
133 ConstantPrimitive(Type Ty, T Value, uint32_t PoolEntryID) 137 ConstantPrimitive(Type Ty, T Value, uint32_t PoolEntryID)
134 : Constant(K, Ty, PoolEntryID), Value(Value) {} 138 : Constant(K, Ty, PoolEntryID), Value(Value) {}
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 static ConstantRelocatable *create(GlobalContext *Ctx, Type Ty, 175 static ConstantRelocatable *create(GlobalContext *Ctx, Type Ty,
172 const RelocatableTuple &Tuple, 176 const RelocatableTuple &Tuple,
173 uint32_t PoolEntryID) { 177 uint32_t PoolEntryID) {
174 return new (Ctx->allocate<ConstantRelocatable>()) ConstantRelocatable( 178 return new (Ctx->allocate<ConstantRelocatable>()) ConstantRelocatable(
175 Ty, Tuple.Offset, Tuple.Name, Tuple.SuppressMangling, PoolEntryID); 179 Ty, Tuple.Offset, Tuple.Name, Tuple.SuppressMangling, PoolEntryID);
176 } 180 }
177 int64_t getOffset() const { return Offset; } 181 int64_t getOffset() const { return Offset; }
178 IceString getName() const { return Name; } 182 IceString getName() const { return Name; }
179 void setSuppressMangling(bool Value) { SuppressMangling = Value; } 183 void setSuppressMangling(bool Value) { SuppressMangling = Value; }
180 bool getSuppressMangling() const { return SuppressMangling; } 184 bool getSuppressMangling() const { return SuppressMangling; }
181 virtual void emit(const Cfg *Func) const; 185 using Constant::emit;
182 virtual void dump(const Cfg *Func) const; 186 using Constant::dump;
187 virtual void emit(GlobalContext *Ctx) const;
188 virtual void dump(GlobalContext *Ctx) const;
183 189
184 static bool classof(const Operand *Operand) { 190 static bool classof(const Operand *Operand) {
185 OperandKind Kind = Operand->getKind(); 191 OperandKind Kind = Operand->getKind();
186 return Kind == kConstRelocatable; 192 return Kind == kConstRelocatable;
187 } 193 }
188 194
189 private: 195 private:
190 ConstantRelocatable(Type Ty, int64_t Offset, const IceString &Name, 196 ConstantRelocatable(Type Ty, int64_t Offset, const IceString &Name,
191 bool SuppressMangling, uint32_t PoolEntryID) 197 bool SuppressMangling, uint32_t PoolEntryID)
192 : Constant(kConstRelocatable, Ty, PoolEntryID), Offset(Offset), 198 : Constant(kConstRelocatable, Ty, PoolEntryID), Offset(Offset),
(...skipping 28 matching lines...) Expand all
221 bool isInf() const { return Weight == Inf; } 227 bool isInf() const { return Weight == Inf; }
222 228
223 private: 229 private:
224 uint32_t Weight; 230 uint32_t Weight;
225 }; 231 };
226 Ostream &operator<<(Ostream &Str, const RegWeight &W); 232 Ostream &operator<<(Ostream &Str, const RegWeight &W);
227 bool operator<(const RegWeight &A, const RegWeight &B); 233 bool operator<(const RegWeight &A, const RegWeight &B);
228 bool operator<=(const RegWeight &A, const RegWeight &B); 234 bool operator<=(const RegWeight &A, const RegWeight &B);
229 bool operator==(const RegWeight &A, const RegWeight &B); 235 bool operator==(const RegWeight &A, const RegWeight &B);
230 236
237 // LiveRange is a set of instruction number intervals representing
238 // a variable's live range. Generally there is one interval per basic
239 // block where the variable is live, but adjacent intervals get
240 // coalesced into a single interval. LiveRange also includes a
241 // weight, in case e.g. we want a live range to have higher weight
242 // inside a loop.
243 class LiveRange {
244 public:
245 LiveRange() : Weight(0) {}
246
247 void reset() {
248 Range.clear();
249 Weight.setWeight(0);
250 }
251 void addSegment(InstNumberT Start, InstNumberT End);
252
253 bool endsBefore(const LiveRange &Other) const;
254 bool overlaps(const LiveRange &Other) const;
255 bool overlaps(InstNumberT OtherBegin) const;
256 bool containsValue(InstNumberT Value) const;
257 bool isEmpty() const { return Range.empty(); }
258 InstNumberT getStart() const {
259 return Range.empty() ? -1 : Range.begin()->first;
260 }
261
262 RegWeight getWeight() const { return Weight; }
263 void setWeight(const RegWeight &NewWeight) { Weight = NewWeight; }
264 void addWeight(uint32_t Delta) { Weight.addWeight(Delta); }
265 void dump(Ostream &Str) const;
266
267 // Defining USE_SET uses std::set to hold the segments instead of
268 // std::list. Using std::list will be slightly faster, but is more
269 // restrictive because new segments cannot be added in the middle.
270
271 //#define USE_SET
272
273 private:
274 typedef std::pair<InstNumberT, InstNumberT> RangeElementType;
275 #ifdef USE_SET
276 typedef std::set<RangeElementType> RangeType;
277 #else
278 typedef std::list<RangeElementType> RangeType;
279 #endif
280 RangeType Range;
281 RegWeight Weight;
282 };
283
284 Ostream &operator<<(Ostream &Str, const LiveRange &L);
285
231 // Variable represents an operand that is register-allocated or 286 // Variable represents an operand that is register-allocated or
232 // stack-allocated. If it is register-allocated, it will ultimately 287 // stack-allocated. If it is register-allocated, it will ultimately
233 // have a non-negative RegNum field. 288 // have a non-negative RegNum field.
234 class Variable : public Operand { 289 class Variable : public Operand {
235 public: 290 public:
236 static Variable *create(Cfg *Func, Type Ty, const CfgNode *Node, SizeT Index, 291 static Variable *create(Cfg *Func, Type Ty, const CfgNode *Node, SizeT Index,
237 const IceString &Name) { 292 const IceString &Name) {
238 return new (Func->allocate<Variable>()) Variable(Ty, Node, Index, Name); 293 return new (Func->allocate<Variable>()) Variable(Ty, Node, Index, Name);
239 } 294 }
240 295
(...skipping 15 matching lines...) Expand all
256 void setStackOffset(int32_t Offset) { StackOffset = Offset; } 311 void setStackOffset(int32_t Offset) { StackOffset = Offset; }
257 312
258 static const int32_t NoRegister = -1; 313 static const int32_t NoRegister = -1;
259 bool hasReg() const { return getRegNum() != NoRegister; } 314 bool hasReg() const { return getRegNum() != NoRegister; }
260 int32_t getRegNum() const { return RegNum; } 315 int32_t getRegNum() const { return RegNum; }
261 void setRegNum(int32_t NewRegNum) { 316 void setRegNum(int32_t NewRegNum) {
262 // Regnum shouldn't be set more than once. 317 // Regnum shouldn't be set more than once.
263 assert(!hasReg() || RegNum == NewRegNum); 318 assert(!hasReg() || RegNum == NewRegNum);
264 RegNum = NewRegNum; 319 RegNum = NewRegNum;
265 } 320 }
321 bool hasRegTmp() const { return getRegNumTmp() != NoRegister; }
322 int32_t getRegNumTmp() const { return RegNumTmp; }
323 void setRegNumTmp(int32_t NewRegNum) { RegNumTmp = NewRegNum; }
266 324
267 RegWeight getWeight() const { return Weight; } 325 RegWeight getWeight() const { return Weight; }
268 void setWeight(uint32_t NewWeight) { Weight = NewWeight; } 326 void setWeight(uint32_t NewWeight) { Weight = NewWeight; }
269 void setWeightInfinite() { Weight = RegWeight::Inf; } 327 void setWeightInfinite() { Weight = RegWeight::Inf; }
270 328
271 Variable *getPreferredRegister() const { return RegisterPreference; } 329 Variable *getPreferredRegister() const { return RegisterPreference; }
272 bool getRegisterOverlap() const { return AllowRegisterOverlap; } 330 bool getRegisterOverlap() const { return AllowRegisterOverlap; }
273 void setPreferredRegister(Variable *Prefer, bool Overlap) { 331 void setPreferredRegister(Variable *Prefer, bool Overlap) {
274 RegisterPreference = Prefer; 332 RegisterPreference = Prefer;
275 AllowRegisterOverlap = Overlap; 333 AllowRegisterOverlap = Overlap;
276 } 334 }
277 335
336 const LiveRange &getLiveRange() const { return Live; }
337 void setLiveRange(const LiveRange &Range) { Live = Range; }
338 void resetLiveRange() { Live.reset(); }
339 void addLiveRange(InstNumberT Start, InstNumberT End, uint32_t WeightDelta) {
340 assert(WeightDelta != RegWeight::Inf);
341 Live.addSegment(Start, End);
342 if (Weight.isInf())
343 Live.setWeight(RegWeight::Inf);
344 else
345 Live.addWeight(WeightDelta * Weight.getWeight());
346 }
347 void setLiveRangeInfiniteWeight() { Live.setWeight(RegWeight::Inf); }
348
278 Variable *getLo() const { return LoVar; } 349 Variable *getLo() const { return LoVar; }
279 Variable *getHi() const { return HiVar; } 350 Variable *getHi() const { return HiVar; }
280 void setLoHi(Variable *Lo, Variable *Hi) { 351 void setLoHi(Variable *Lo, Variable *Hi) {
281 assert(LoVar == NULL); 352 assert(LoVar == NULL);
282 assert(HiVar == NULL); 353 assert(HiVar == NULL);
283 LoVar = Lo; 354 LoVar = Lo;
284 HiVar = Hi; 355 HiVar = Hi;
285 } 356 }
286 // Creates a temporary copy of the variable with a different type. 357 // Creates a temporary copy of the variable with a different type.
287 // Used primarily for syntactic correctness of textual assembly 358 // Used primarily for syntactic correctness of textual assembly
288 // emission. Note that only basic information is copied, in 359 // emission. Note that only basic information is copied, in
289 // particular not DefInst, IsArgument, Weight, RegisterPreference, 360 // particular not DefInst, IsArgument, Weight, RegisterPreference,
290 // AllowRegisterOverlap, LoVar, HiVar, VarsReal. 361 // AllowRegisterOverlap, LoVar, HiVar, VarsReal.
291 Variable asType(Type Ty); 362 Variable asType(Type Ty);
292 363
293 virtual void emit(const Cfg *Func) const; 364 virtual void emit(const Cfg *Func) const;
294 virtual void dump(const Cfg *Func) const; 365 virtual void dump(const Cfg *Func) const;
295 366
296 static bool classof(const Operand *Operand) { 367 static bool classof(const Operand *Operand) {
297 return Operand->getKind() == kVariable; 368 return Operand->getKind() == kVariable;
298 } 369 }
299 370
300 // The destructor is public because of the asType() method. 371 // The destructor is public because of the asType() method.
301 virtual ~Variable() {} 372 virtual ~Variable() {}
302 373
303 private: 374 private:
304 Variable(Type Ty, const CfgNode *Node, SizeT Index, const IceString &Name) 375 Variable(Type Ty, const CfgNode *Node, SizeT Index, const IceString &Name)
305 : Operand(kVariable, Ty), Number(Index), Name(Name), DefInst(NULL), 376 : Operand(kVariable, Ty), Number(Index), Name(Name), DefInst(NULL),
306 DefNode(Node), IsArgument(false), StackOffset(0), RegNum(NoRegister), 377 DefNode(Node), IsArgument(false), StackOffset(0), RegNum(NoRegister),
307 Weight(1), RegisterPreference(NULL), AllowRegisterOverlap(false), 378 RegNumTmp(NoRegister), Weight(1), RegisterPreference(NULL),
308 LoVar(NULL), HiVar(NULL) { 379 AllowRegisterOverlap(false), LoVar(NULL), HiVar(NULL) {
309 Vars = VarsReal; 380 Vars = VarsReal;
310 Vars[0] = this; 381 Vars[0] = this;
311 NumVars = 1; 382 NumVars = 1;
312 } 383 }
313 Variable(const Variable &) LLVM_DELETED_FUNCTION; 384 Variable(const Variable &) LLVM_DELETED_FUNCTION;
314 Variable &operator=(const Variable &) LLVM_DELETED_FUNCTION; 385 Variable &operator=(const Variable &) LLVM_DELETED_FUNCTION;
315 // Number is unique across all variables, and is used as a 386 // Number is unique across all variables, and is used as a
316 // (bit)vector index for liveness analysis. 387 // (bit)vector index for liveness analysis.
317 const SizeT Number; 388 const SizeT Number;
318 // Name is optional. 389 // Name is optional.
319 const IceString Name; 390 const IceString Name;
320 // DefInst is the instruction that produces this variable as its 391 // DefInst is the instruction that produces this variable as its
321 // dest. 392 // dest.
322 Inst *DefInst; 393 Inst *DefInst;
323 // DefNode is the node where this variable was produced, and is 394 // DefNode is the node where this variable was produced, and is
324 // reset to NULL if it is used outside that node. This is used for 395 // reset to NULL if it is used outside that node. This is used for
325 // detecting isMultiblockLife(). TODO: Collapse this to a single 396 // detecting isMultiblockLife(). TODO: Collapse this to a single
326 // bit and use a separate pass to calculate the values across the 397 // bit and use a separate pass to calculate the values across the
327 // Cfg. This saves space in the Variable, and removes the fragility 398 // Cfg. This saves space in the Variable, and removes the fragility
328 // of incrementally computing and maintaining the information. 399 // of incrementally computing and maintaining the information.
329 const CfgNode *DefNode; 400 const CfgNode *DefNode;
330 bool IsArgument; 401 bool IsArgument;
331 // StackOffset is the canonical location on stack (only if 402 // StackOffset is the canonical location on stack (only if
332 // RegNum<0 || IsArgument). 403 // RegNum<0 || IsArgument).
333 int32_t StackOffset; 404 int32_t StackOffset;
334 // RegNum is the allocated register, or NoRegister if it isn't 405 // RegNum is the allocated register, or NoRegister if it isn't
335 // register-allocated. 406 // register-allocated.
336 int32_t RegNum; 407 int32_t RegNum;
408 // RegNumTmp is the tentative assignment during register allocation.
409 int32_t RegNumTmp;
337 RegWeight Weight; // Register allocation priority 410 RegWeight Weight; // Register allocation priority
338 // RegisterPreference says that if possible, the register allocator 411 // RegisterPreference says that if possible, the register allocator
339 // should prefer the register that was assigned to this linked 412 // should prefer the register that was assigned to this linked
340 // variable. It also allows a spill slot to share its stack 413 // variable. It also allows a spill slot to share its stack
341 // location with another variable, if that variable does not get 414 // location with another variable, if that variable does not get
342 // register-allocated and therefore has a stack location. 415 // register-allocated and therefore has a stack location.
343 Variable *RegisterPreference; 416 Variable *RegisterPreference;
344 // AllowRegisterOverlap says that it is OK to honor 417 // AllowRegisterOverlap says that it is OK to honor
345 // RegisterPreference and "share" a register even if the two live 418 // RegisterPreference and "share" a register even if the two live
346 // ranges overlap. 419 // ranges overlap.
347 bool AllowRegisterOverlap; 420 bool AllowRegisterOverlap;
421 LiveRange Live;
348 // LoVar and HiVar are needed for lowering from 64 to 32 bits. When 422 // LoVar and HiVar are needed for lowering from 64 to 32 bits. When
349 // lowering from I64 to I32 on a 32-bit architecture, we split the 423 // lowering from I64 to I32 on a 32-bit architecture, we split the
350 // variable into two machine-size pieces. LoVar is the low-order 424 // variable into two machine-size pieces. LoVar is the low-order
351 // machine-size portion, and HiVar is the remaining high-order 425 // machine-size portion, and HiVar is the remaining high-order
352 // portion. TODO: It's wasteful to penalize all variables on all 426 // portion. TODO: It's wasteful to penalize all variables on all
353 // targets this way; use a sparser representation. It's also 427 // targets this way; use a sparser representation. It's also
354 // wasteful for a 64-bit target. 428 // wasteful for a 64-bit target.
355 Variable *LoVar; 429 Variable *LoVar;
356 Variable *HiVar; 430 Variable *HiVar;
357 // VarsReal (and Operand::Vars) are set up such that Vars[0] == 431 // VarsReal (and Operand::Vars) are set up such that Vars[0] ==
358 // this. 432 // this.
359 Variable *VarsReal[1]; 433 Variable *VarsReal[1];
360 }; 434 };
361 435
362 } // end of namespace Ice 436 } // end of namespace Ice
363 437
364 #endif // SUBZERO_SRC_ICEOPERAND_H 438 #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