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 |