| 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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 55 // the operand. This is so that the liveness operations can get | 55 // the operand. This is so that the liveness operations can get |
| 56 // quick access to the variables of interest, without having to dig | 56 // quick access to the variables of interest, without having to dig |
| 57 // so far into the operand. | 57 // so far into the operand. |
| 58 SizeT getNumVars() const { return NumVars; } | 58 SizeT getNumVars() const { return NumVars; } |
| 59 Variable *getVar(SizeT I) const { | 59 Variable *getVar(SizeT I) const { |
| 60 assert(I < getNumVars()); | 60 assert(I < getNumVars()); |
| 61 return Vars[I]; | 61 return Vars[I]; |
| 62 } | 62 } |
| 63 virtual void emit(const Cfg *Func) const = 0; | 63 virtual void emit(const Cfg *Func) const = 0; |
| 64 // The dump(Func,Str) implementation must be sure to handle the | 64 // The dump(Func,Str) implementation must be sure to handle the |
| 65 // situation where Func==NULL. | 65 // situation where Func==nullptr. |
| 66 virtual void dump(const Cfg *Func, Ostream &Str) const = 0; | 66 virtual void dump(const Cfg *Func, Ostream &Str) const = 0; |
| 67 void dump(const Cfg *Func) const { | 67 void dump(const Cfg *Func) const { |
| 68 if (!ALLOW_DUMP) | 68 if (!ALLOW_DUMP) |
| 69 return; | 69 return; |
| 70 assert(Func); | 70 assert(Func); |
| 71 dump(Func, Func->getContext()->getStrDump()); | 71 dump(Func, Func->getContext()->getStrDump()); |
| 72 } | 72 } |
| 73 void dump(Ostream &Str) const { | 73 void dump(Ostream &Str) const { |
| 74 if (ALLOW_DUMP) | 74 if (ALLOW_DUMP) |
| 75 dump(NULL, Str); | 75 dump(nullptr, Str); |
| 76 } | 76 } |
| 77 | 77 |
| 78 // Query whether this object was allocated in isolation, or added to | 78 // Query whether this object was allocated in isolation, or added to |
| 79 // some higher-level pool. This determines whether a containing | 79 // some higher-level pool. This determines whether a containing |
| 80 // object's destructor should delete this object. Generally, | 80 // object's destructor should delete this object. Generally, |
| 81 // constants are pooled globally, variables are pooled per-CFG, and | 81 // constants are pooled globally, variables are pooled per-CFG, and |
| 82 // target-specific operands are not pooled. | 82 // target-specific operands are not pooled. |
| 83 virtual bool isPooled() const { return false; } | 83 virtual bool isPooled() const { return false; } |
| 84 | 84 |
| 85 virtual ~Operand() {} | 85 virtual ~Operand() {} |
| 86 | 86 |
| 87 protected: | 87 protected: |
| 88 Operand(OperandKind Kind, Type Ty) | 88 Operand(OperandKind Kind, Type Ty) |
| 89 : Ty(Ty), Kind(Kind), NumVars(0), Vars(NULL) {} | 89 : Ty(Ty), Kind(Kind), NumVars(0), Vars(nullptr) {} |
| 90 | 90 |
| 91 const Type Ty; | 91 const Type Ty; |
| 92 const OperandKind Kind; | 92 const OperandKind Kind; |
| 93 // Vars and NumVars are initialized by the derived class. | 93 // Vars and NumVars are initialized by the derived class. |
| 94 SizeT NumVars; | 94 SizeT NumVars; |
| 95 Variable **Vars; | 95 Variable **Vars; |
| 96 }; | 96 }; |
| 97 | 97 |
| 98 template<class StreamType> | 98 template<class StreamType> |
| 99 inline StreamType &operator<<(StreamType &Str, const Operand &Op) { | 99 inline StreamType &operator<<(StreamType &Str, const Operand &Op) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 115 void dump(const Cfg *Func, Ostream &Str) const = 0; | 115 void dump(const Cfg *Func, Ostream &Str) const = 0; |
| 116 | 116 |
| 117 static bool classof(const Operand *Operand) { | 117 static bool classof(const Operand *Operand) { |
| 118 OperandKind Kind = Operand->getKind(); | 118 OperandKind Kind = Operand->getKind(); |
| 119 return Kind >= kConst_Base && Kind <= kConst_Num; | 119 return Kind >= kConst_Base && Kind <= kConst_Num; |
| 120 } | 120 } |
| 121 | 121 |
| 122 protected: | 122 protected: |
| 123 Constant(OperandKind Kind, Type Ty, uint32_t PoolEntryID) | 123 Constant(OperandKind Kind, Type Ty, uint32_t PoolEntryID) |
| 124 : Operand(Kind, Ty), PoolEntryID(PoolEntryID) { | 124 : Operand(Kind, Ty), PoolEntryID(PoolEntryID) { |
| 125 Vars = NULL; | 125 Vars = nullptr; |
| 126 NumVars = 0; | 126 NumVars = 0; |
| 127 } | 127 } |
| 128 ~Constant() override {} | 128 ~Constant() override {} |
| 129 // PoolEntryID is an integer that uniquely identifies the constant | 129 // PoolEntryID is an integer that uniquely identifies the constant |
| 130 // within its constant pool. It is used for building the constant | 130 // within its constant pool. It is used for building the constant |
| 131 // pool in the object code and for referencing its entries. | 131 // pool in the object code and for referencing its entries. |
| 132 const uint32_t PoolEntryID; | 132 const uint32_t PoolEntryID; |
| 133 }; | 133 }; |
| 134 | 134 |
| 135 // ConstantPrimitive<> wraps a primitive type. | 135 // ConstantPrimitive<> wraps a primitive type. |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 450 return Live.overlaps(Other->Live, UseTrimmed); | 450 return Live.overlaps(Other->Live, UseTrimmed); |
| 451 } | 451 } |
| 452 bool rangeOverlapsStart(const Variable *Other) const { | 452 bool rangeOverlapsStart(const Variable *Other) const { |
| 453 const bool UseTrimmed = true; | 453 const bool UseTrimmed = true; |
| 454 return Live.overlapsInst(Other->Live.getStart(), UseTrimmed); | 454 return Live.overlapsInst(Other->Live.getStart(), UseTrimmed); |
| 455 } | 455 } |
| 456 | 456 |
| 457 Variable *getLo() const { return LoVar; } | 457 Variable *getLo() const { return LoVar; } |
| 458 Variable *getHi() const { return HiVar; } | 458 Variable *getHi() const { return HiVar; } |
| 459 void setLoHi(Variable *Lo, Variable *Hi) { | 459 void setLoHi(Variable *Lo, Variable *Hi) { |
| 460 assert(LoVar == NULL); | 460 assert(LoVar == nullptr); |
| 461 assert(HiVar == NULL); | 461 assert(HiVar == nullptr); |
| 462 LoVar = Lo; | 462 LoVar = Lo; |
| 463 HiVar = Hi; | 463 HiVar = Hi; |
| 464 } | 464 } |
| 465 // Creates a temporary copy of the variable with a different type. | 465 // Creates a temporary copy of the variable with a different type. |
| 466 // Used primarily for syntactic correctness of textual assembly | 466 // Used primarily for syntactic correctness of textual assembly |
| 467 // emission. Note that only basic information is copied, in | 467 // emission. Note that only basic information is copied, in |
| 468 // particular not IsArgument, IsImplicitArgument, IgnoreLiveness, | 468 // particular not IsArgument, IsImplicitArgument, IgnoreLiveness, |
| 469 // RegNumTmp, Weight, Live, LoVar, HiVar, VarsReal. | 469 // RegNumTmp, Weight, Live, LoVar, HiVar, VarsReal. |
| 470 Variable *asType(Type Ty); | 470 Variable *asType(Type Ty); |
| 471 | 471 |
| 472 void emit(const Cfg *Func) const override; | 472 void emit(const Cfg *Func) const override; |
| 473 using Operand::dump; | 473 using Operand::dump; |
| 474 void dump(const Cfg *Func, Ostream &Str) const override; | 474 void dump(const Cfg *Func, Ostream &Str) const override; |
| 475 | 475 |
| 476 static bool classof(const Operand *Operand) { | 476 static bool classof(const Operand *Operand) { |
| 477 OperandKind Kind = Operand->getKind(); | 477 OperandKind Kind = Operand->getKind(); |
| 478 return Kind >= kVariable && Kind <= kVariable_Num; | 478 return Kind >= kVariable && Kind <= kVariable_Num; |
| 479 } | 479 } |
| 480 | 480 |
| 481 protected: | 481 protected: |
| 482 Variable(OperandKind K, Type Ty, SizeT Index) | 482 Variable(OperandKind K, Type Ty, SizeT Index) |
| 483 : Operand(K, Ty), Number(Index), NameIndex(Cfg::IdentifierIndexInvalid), | 483 : Operand(K, Ty), Number(Index), NameIndex(Cfg::IdentifierIndexInvalid), |
| 484 IsArgument(false), IsImplicitArgument(false), IgnoreLiveness(false), | 484 IsArgument(false), IsImplicitArgument(false), IgnoreLiveness(false), |
| 485 StackOffset(0), RegNum(NoRegister), RegNumTmp(NoRegister), Weight(1), | 485 StackOffset(0), RegNum(NoRegister), RegNumTmp(NoRegister), Weight(1), |
| 486 LoVar(NULL), HiVar(NULL) { | 486 LoVar(nullptr), HiVar(nullptr) { |
| 487 Vars = VarsReal; | 487 Vars = VarsReal; |
| 488 Vars[0] = this; | 488 Vars[0] = this; |
| 489 NumVars = 1; | 489 NumVars = 1; |
| 490 } | 490 } |
| 491 ~Variable() override {} | 491 ~Variable() override {} |
| 492 // Number is unique across all variables, and is used as a | 492 // Number is unique across all variables, and is used as a |
| 493 // (bit)vector index for liveness analysis. | 493 // (bit)vector index for liveness analysis. |
| 494 const SizeT Number; | 494 const SizeT Number; |
| 495 Cfg::IdentifierIndexType NameIndex; | 495 Cfg::IdentifierIndexType NameIndex; |
| 496 bool IsArgument; | 496 bool IsArgument; |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 543 MDS_SingleDef, | 543 MDS_SingleDef, |
| 544 MDS_MultiDefSingleBlock, | 544 MDS_MultiDefSingleBlock, |
| 545 MDS_MultiDefMultiBlock | 545 MDS_MultiDefMultiBlock |
| 546 }; | 546 }; |
| 547 enum MultiBlockState { | 547 enum MultiBlockState { |
| 548 MBS_Unknown, | 548 MBS_Unknown, |
| 549 MBS_SingleBlock, | 549 MBS_SingleBlock, |
| 550 MBS_MultiBlock | 550 MBS_MultiBlock |
| 551 }; | 551 }; |
| 552 VariableTracking() | 552 VariableTracking() |
| 553 : MultiDef(MDS_Unknown), MultiBlock(MBS_Unknown), SingleUseNode(NULL), | 553 : MultiDef(MDS_Unknown), MultiBlock(MBS_Unknown), SingleUseNode(nullptr), |
| 554 SingleDefNode(NULL), FirstOrSingleDefinition(NULL) {} | 554 SingleDefNode(nullptr), FirstOrSingleDefinition(nullptr) {} |
| 555 MultiDefState getMultiDef() const { return MultiDef; } | 555 MultiDefState getMultiDef() const { return MultiDef; } |
| 556 MultiBlockState getMultiBlock() const { return MultiBlock; } | 556 MultiBlockState getMultiBlock() const { return MultiBlock; } |
| 557 const Inst *getFirstDefinition() const; | 557 const Inst *getFirstDefinition() const; |
| 558 const Inst *getSingleDefinition() const; | 558 const Inst *getSingleDefinition() const; |
| 559 const InstDefList &getLatterDefinitions() const { return Definitions; } | 559 const InstDefList &getLatterDefinitions() const { return Definitions; } |
| 560 const CfgNode *getNode() const { return SingleUseNode; } | 560 const CfgNode *getNode() const { return SingleUseNode; } |
| 561 void markUse(MetadataKind TrackingKind, const Inst *Instr, | 561 void markUse(MetadataKind TrackingKind, const Inst *Instr, |
| 562 const CfgNode *Node, bool IsFromDef, bool IsImplicit); | 562 const CfgNode *Node, bool IsFromDef, bool IsImplicit); |
| 563 void markDef(MetadataKind TrackingKind, const Inst *Instr, | 563 void markDef(MetadataKind TrackingKind, const Inst *Instr, |
| 564 const CfgNode *Node); | 564 const CfgNode *Node); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 596 return Var->getIndex() < Metadata.size(); | 596 return Var->getIndex() < Metadata.size(); |
| 597 } | 597 } |
| 598 | 598 |
| 599 // Returns whether the given Variable has multiple definitions. | 599 // Returns whether the given Variable has multiple definitions. |
| 600 bool isMultiDef(const Variable *Var) const; | 600 bool isMultiDef(const Variable *Var) const; |
| 601 // Returns the first definition instruction of the given Variable. | 601 // Returns the first definition instruction of the given Variable. |
| 602 // This is only valid for variables whose definitions are all within | 602 // This is only valid for variables whose definitions are all within |
| 603 // the same block, e.g. T after the lowered sequence "T=B; T+=C; | 603 // the same block, e.g. T after the lowered sequence "T=B; T+=C; |
| 604 // A=T", for which getFirstDefinition(T) would return the "T=B" | 604 // A=T", for which getFirstDefinition(T) would return the "T=B" |
| 605 // instruction. For variables with definitions span multiple | 605 // instruction. For variables with definitions span multiple |
| 606 // blocks, NULL is returned. | 606 // blocks, nullptr is returned. |
| 607 const Inst *getFirstDefinition(const Variable *Var) const; | 607 const Inst *getFirstDefinition(const Variable *Var) const; |
| 608 // Returns the definition instruction of the given Variable, when | 608 // Returns the definition instruction of the given Variable, when |
| 609 // the variable has exactly one definition. Otherwise, NULL is | 609 // the variable has exactly one definition. Otherwise, nullptr is |
| 610 // returned. | 610 // returned. |
| 611 const Inst *getSingleDefinition(const Variable *Var) const; | 611 const Inst *getSingleDefinition(const Variable *Var) const; |
| 612 // Returns the list of all definition instructions of the given | 612 // Returns the list of all definition instructions of the given |
| 613 // Variable. | 613 // Variable. |
| 614 const InstDefList &getLatterDefinitions(const Variable *Var) const; | 614 const InstDefList &getLatterDefinitions(const Variable *Var) const; |
| 615 | 615 |
| 616 // Returns whether the given Variable is live across multiple | 616 // Returns whether the given Variable is live across multiple |
| 617 // blocks. Mainly, this is used to partition Variables into | 617 // blocks. Mainly, this is used to partition Variables into |
| 618 // single-block versus multi-block sets for leveraging sparsity in | 618 // single-block versus multi-block sets for leveraging sparsity in |
| 619 // liveness analysis, and for implementing simple stack slot | 619 // liveness analysis, and for implementing simple stack slot |
| 620 // coalescing. As a special case, function arguments are always | 620 // coalescing. As a special case, function arguments are always |
| 621 // considered multi-block because they are live coming into the | 621 // considered multi-block because they are live coming into the |
| 622 // entry block. | 622 // entry block. |
| 623 bool isMultiBlock(const Variable *Var) const; | 623 bool isMultiBlock(const Variable *Var) const; |
| 624 // Returns the node that the given Variable is used in, assuming | 624 // Returns the node that the given Variable is used in, assuming |
| 625 // isMultiBlock() returns false. Otherwise, NULL is returned. | 625 // isMultiBlock() returns false. Otherwise, nullptr is returned. |
| 626 const CfgNode *getLocalUseNode(const Variable *Var) const; | 626 const CfgNode *getLocalUseNode(const Variable *Var) const; |
| 627 | 627 |
| 628 private: | 628 private: |
| 629 const Cfg *Func; | 629 const Cfg *Func; |
| 630 MetadataKind Kind; | 630 MetadataKind Kind; |
| 631 std::vector<VariableTracking> Metadata; | 631 std::vector<VariableTracking> Metadata; |
| 632 const static InstDefList NoDefinitions; | 632 const static InstDefList NoDefinitions; |
| 633 }; | 633 }; |
| 634 | 634 |
| 635 } // end of namespace Ice | 635 } // end of namespace Ice |
| 636 | 636 |
| 637 #endif // SUBZERO_SRC_ICEOPERAND_H | 637 #endif // SUBZERO_SRC_ICEOPERAND_H |
| OLD | NEW |