OLD | NEW |
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 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
340 Ostream &operator<<(Ostream &Str, const LiveRange &L); | 340 Ostream &operator<<(Ostream &Str, const LiveRange &L); |
341 | 341 |
342 // Variable represents an operand that is register-allocated or | 342 // Variable represents an operand that is register-allocated or |
343 // stack-allocated. If it is register-allocated, it will ultimately | 343 // stack-allocated. If it is register-allocated, it will ultimately |
344 // have a non-negative RegNum field. | 344 // have a non-negative RegNum field. |
345 class Variable : public Operand { | 345 class Variable : public Operand { |
346 Variable(const Variable &) LLVM_DELETED_FUNCTION; | 346 Variable(const Variable &) LLVM_DELETED_FUNCTION; |
347 Variable &operator=(const Variable &) LLVM_DELETED_FUNCTION; | 347 Variable &operator=(const Variable &) LLVM_DELETED_FUNCTION; |
348 | 348 |
349 public: | 349 public: |
350 static Variable *create(Cfg *Func, Type Ty, const CfgNode *Node, SizeT Index, | 350 static Variable *create(Cfg *Func, Type Ty, SizeT Index, |
351 const IceString &Name) { | 351 const IceString &Name) { |
352 return new (Func->allocate<Variable>()) | 352 return new (Func->allocate<Variable>()) |
353 Variable(kVariable, Ty, Node, Index, Name); | 353 Variable(kVariable, Ty, Index, Name); |
354 } | 354 } |
355 | 355 |
356 SizeT getIndex() const { return Number; } | 356 SizeT getIndex() const { return Number; } |
357 IceString getName() const; | 357 IceString getName() const; |
358 void setName(IceString &NewName) { | 358 void setName(IceString &NewName) { |
359 // Make sure that the name can only be set once. | 359 // Make sure that the name can only be set once. |
360 assert(Name.empty()); | 360 assert(Name.empty()); |
361 Name = NewName; | 361 Name = NewName; |
362 } | 362 } |
363 | 363 |
364 Inst *getDefinition() const { return DefInst; } | |
365 void setDefinition(Inst *Inst, const CfgNode *Node); | |
366 void replaceDefinition(Inst *Inst, const CfgNode *Node); | |
367 | |
368 const CfgNode *getLocalUseNode() const { return DefNode; } | |
369 bool isMultiblockLife() const { return (DefNode == NULL); } | |
370 void setUse(const Inst *Inst, const CfgNode *Node); | |
371 | |
372 // Multidef means a variable is non-SSA and has multiple defining | |
373 // instructions. Currently this classification is limited to SSA | |
374 // lowering temporaries where the definitions are in different basic | |
375 // blocks, and it is not maintained during target lowering when the | |
376 // same temporary may be updated in consecutive instructions. | |
377 bool getIsMultidef() const { return IsMultidef; } | |
378 void setIsMultidef() { IsMultidef = true; } | |
379 | |
380 bool getIsArg() const { return IsArgument; } | 364 bool getIsArg() const { return IsArgument; } |
381 void setIsArg(Cfg *Func, bool IsArg = true); | 365 void setIsArg(bool Val = true) { IsArgument = Val; } |
| 366 bool getIsImplicitArg() const { return IsImplicitArgument; } |
| 367 void setIsImplicitArg(bool Val = true) { IsImplicitArgument = Val; } |
382 | 368 |
383 int32_t getStackOffset() const { return StackOffset; } | 369 int32_t getStackOffset() const { return StackOffset; } |
384 void setStackOffset(int32_t Offset) { StackOffset = Offset; } | 370 void setStackOffset(int32_t Offset) { StackOffset = Offset; } |
385 | 371 |
386 static const int32_t NoRegister = -1; | 372 static const int32_t NoRegister = -1; |
387 bool hasReg() const { return getRegNum() != NoRegister; } | 373 bool hasReg() const { return getRegNum() != NoRegister; } |
388 int32_t getRegNum() const { return RegNum; } | 374 int32_t getRegNum() const { return RegNum; } |
389 void setRegNum(int32_t NewRegNum) { | 375 void setRegNum(int32_t NewRegNum) { |
390 // Regnum shouldn't be set more than once. | 376 // Regnum shouldn't be set more than once. |
391 assert(!hasReg() || RegNum == NewRegNum); | 377 assert(!hasReg() || RegNum == NewRegNum); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
440 | 426 |
441 static bool classof(const Operand *Operand) { | 427 static bool classof(const Operand *Operand) { |
442 OperandKind Kind = Operand->getKind(); | 428 OperandKind Kind = Operand->getKind(); |
443 return Kind >= kVariable && Kind <= kVariable_Num; | 429 return Kind >= kVariable && Kind <= kVariable_Num; |
444 } | 430 } |
445 | 431 |
446 // The destructor is public because of the asType() method. | 432 // The destructor is public because of the asType() method. |
447 virtual ~Variable() {} | 433 virtual ~Variable() {} |
448 | 434 |
449 protected: | 435 protected: |
450 Variable(OperandKind K, Type Ty, const CfgNode *Node, SizeT Index, | 436 Variable(OperandKind K, Type Ty, SizeT Index, const IceString &Name) |
451 const IceString &Name) | 437 : Operand(K, Ty), Number(Index), Name(Name), IsArgument(false), |
452 : Operand(K, Ty), Number(Index), Name(Name), DefInst(NULL), DefNode(Node), | 438 IsImplicitArgument(false), StackOffset(0), RegNum(NoRegister), |
453 IsMultidef(false), IsArgument(false), StackOffset(0), | 439 RegNumTmp(NoRegister), Weight(1), RegisterPreference(NULL), |
454 RegNum(NoRegister), RegNumTmp(NoRegister), Weight(1), | 440 AllowRegisterOverlap(false), LoVar(NULL), HiVar(NULL) { |
455 RegisterPreference(NULL), AllowRegisterOverlap(false), LoVar(NULL), | |
456 HiVar(NULL) { | |
457 Vars = VarsReal; | 441 Vars = VarsReal; |
458 Vars[0] = this; | 442 Vars[0] = this; |
459 NumVars = 1; | 443 NumVars = 1; |
460 } | 444 } |
461 // Number is unique across all variables, and is used as a | 445 // Number is unique across all variables, and is used as a |
462 // (bit)vector index for liveness analysis. | 446 // (bit)vector index for liveness analysis. |
463 const SizeT Number; | 447 const SizeT Number; |
464 // Name is optional. | 448 // Name is optional. |
465 IceString Name; | 449 IceString Name; |
466 // DefInst is the instruction that produces this variable as its | |
467 // dest. | |
468 Inst *DefInst; | |
469 // DefNode is the node where this variable was produced, and is | |
470 // reset to NULL if it is used outside that node. This is used for | |
471 // detecting isMultiblockLife(). TODO: Collapse this to a single | |
472 // bit and use a separate pass to calculate the values across the | |
473 // Cfg. This saves space in the Variable, and removes the fragility | |
474 // of incrementally computing and maintaining the information. | |
475 const CfgNode *DefNode; | |
476 bool IsMultidef; | |
477 bool IsArgument; | 450 bool IsArgument; |
| 451 bool IsImplicitArgument; |
478 // StackOffset is the canonical location on stack (only if | 452 // StackOffset is the canonical location on stack (only if |
479 // RegNum<0 || IsArgument). | 453 // RegNum<0 || IsArgument). |
480 int32_t StackOffset; | 454 int32_t StackOffset; |
481 // RegNum is the allocated register, or NoRegister if it isn't | 455 // RegNum is the allocated register, or NoRegister if it isn't |
482 // register-allocated. | 456 // register-allocated. |
483 int32_t RegNum; | 457 int32_t RegNum; |
484 // RegNumTmp is the tentative assignment during register allocation. | 458 // RegNumTmp is the tentative assignment during register allocation. |
485 int32_t RegNumTmp; | 459 int32_t RegNumTmp; |
486 RegWeight Weight; // Register allocation priority | 460 RegWeight Weight; // Register allocation priority |
487 // RegisterPreference says that if possible, the register allocator | 461 // RegisterPreference says that if possible, the register allocator |
(...skipping 14 matching lines...) Expand all Loading... |
502 // portion. TODO: It's wasteful to penalize all variables on all | 476 // portion. TODO: It's wasteful to penalize all variables on all |
503 // targets this way; use a sparser representation. It's also | 477 // targets this way; use a sparser representation. It's also |
504 // wasteful for a 64-bit target. | 478 // wasteful for a 64-bit target. |
505 Variable *LoVar; | 479 Variable *LoVar; |
506 Variable *HiVar; | 480 Variable *HiVar; |
507 // VarsReal (and Operand::Vars) are set up such that Vars[0] == | 481 // VarsReal (and Operand::Vars) are set up such that Vars[0] == |
508 // this. | 482 // this. |
509 Variable *VarsReal[1]; | 483 Variable *VarsReal[1]; |
510 }; | 484 }; |
511 | 485 |
| 486 // VariableTracking tracks the metadata for a single variable. |
| 487 class VariableTracking { |
| 488 public: |
| 489 enum MultiDefState { |
| 490 // TODO(stichnot): Consider using just a simple counter. |
| 491 MDS_Unknown, |
| 492 MDS_SingleDef, |
| 493 MDS_MultiDef |
| 494 }; |
| 495 enum MultiBlockState { |
| 496 MBS_Unknown, |
| 497 MBS_SingleBlock, |
| 498 MBS_MultiBlock |
| 499 }; |
| 500 VariableTracking() |
| 501 : MultiDef(MDS_Unknown), MultiBlock(MBS_Unknown), SingleUseNode(NULL), |
| 502 SingleDefInst(NULL) {} |
| 503 MultiDefState getMultiDef() const { return MultiDef; } |
| 504 MultiBlockState getMultiBlock() const { return MultiBlock; } |
| 505 const Inst *getDefinition() const { return SingleDefInst; } |
| 506 const CfgNode *getNode() const { return SingleUseNode; } |
| 507 void markUse(const Inst *Instr, const CfgNode *Node, bool IsFromDef, |
| 508 bool IsImplicit); |
| 509 void markDef(const Inst *Instr, const CfgNode *Node); |
| 510 |
| 511 private: |
| 512 VariableTracking &operator=(const VariableTracking &) LLVM_DELETED_FUNCTION; |
| 513 MultiDefState MultiDef; |
| 514 MultiBlockState MultiBlock; |
| 515 const CfgNode *SingleUseNode; |
| 516 const Inst *SingleDefInst; |
| 517 }; |
| 518 |
| 519 // VariablesMetadata analyzes and summarizes the metadata for the |
| 520 // complete set of Variables. |
| 521 class VariablesMetadata { |
| 522 public: |
| 523 VariablesMetadata(const Cfg *Func) : Func(Func) {} |
| 524 void init(); |
| 525 bool isTracked(const Variable *Var) const { |
| 526 return Var->getIndex() < Metadata.size(); |
| 527 } |
| 528 bool isMultiDef(const Variable *Var) const; |
| 529 const Inst *getDefinition(const Variable *Var) const; |
| 530 bool isMultiBlock(const Variable *Var) const; |
| 531 const CfgNode *getLocalUseNode(const Variable *Var) const; |
| 532 |
| 533 private: |
| 534 const Cfg *Func; |
| 535 std::vector<VariableTracking> Metadata; |
| 536 VariablesMetadata(const VariablesMetadata &) LLVM_DELETED_FUNCTION; |
| 537 VariablesMetadata &operator=(const VariablesMetadata &) LLVM_DELETED_FUNCTION; |
| 538 }; |
| 539 |
512 } // end of namespace Ice | 540 } // end of namespace Ice |
513 | 541 |
514 #endif // SUBZERO_SRC_ICEOPERAND_H | 542 #endif // SUBZERO_SRC_ICEOPERAND_H |
OLD | NEW |