| 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 /// \file | 10 /// \file |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 kConst_Base, | 36 kConst_Base, |
| 37 kConstInteger32, | 37 kConstInteger32, |
| 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 kVariable64On32, |
| 46 kVariable_Target, // leave space for target-specific variable kinds | 47 kVariable_Target, // leave space for target-specific variable kinds |
| 47 kVariable_Max = kVariable_Target + MaxTargetKinds, | 48 kVariable_Max = kVariable_Target + MaxTargetKinds, |
| 48 // Target-specific operand classes use kTarget as the starting point for | 49 // Target-specific operand classes use kTarget as the starting point for |
| 49 // their Kind enum space. Note that the value-spaces are shared across | 50 // their Kind enum space. Note that the value-spaces are shared across |
| 50 // targets. To avoid confusion over the definition of shared values, an | 51 // targets. To avoid confusion over the definition of shared values, an |
| 51 // object specific to one target should never be passed to a different | 52 // object specific to one target should never be passed to a different |
| 52 // target. | 53 // target. |
| 53 kTarget, | 54 kTarget, |
| 54 kTarget_Max = std::numeric_limits<uint8_t>::max(), | 55 kTarget_Max = std::numeric_limits<uint8_t>::max(), |
| 55 }; | 56 }; |
| (...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 404 Ostream &operator<<(Ostream &Str, const LiveRange &L); | 405 Ostream &operator<<(Ostream &Str, const LiveRange &L); |
| 405 | 406 |
| 406 /// Variable represents an operand that is register-allocated or | 407 /// Variable represents an operand that is register-allocated or |
| 407 /// stack-allocated. If it is register-allocated, it will ultimately have a | 408 /// stack-allocated. If it is register-allocated, it will ultimately have a |
| 408 /// non-negative RegNum field. | 409 /// non-negative RegNum field. |
| 409 class Variable : public Operand { | 410 class Variable : public Operand { |
| 410 Variable() = delete; | 411 Variable() = delete; |
| 411 Variable(const Variable &) = delete; | 412 Variable(const Variable &) = delete; |
| 412 Variable &operator=(const Variable &) = delete; | 413 Variable &operator=(const Variable &) = delete; |
| 413 | 414 |
| 414 enum RegRequirement { | 415 enum RegRequirement : uint8_t { |
| 415 RR_MayHaveRegister, | 416 RR_MayHaveRegister, |
| 416 RR_MustHaveRegister, | 417 RR_MustHaveRegister, |
| 417 RR_MustNotHaveRegister, | 418 RR_MustNotHaveRegister, |
| 418 }; | 419 }; |
| 419 | 420 |
| 420 public: | 421 public: |
| 421 static Variable *create(Cfg *Func, Type Ty, SizeT Index) { | 422 static Variable *create(Cfg *Func, Type Ty, SizeT Index) { |
| 422 return new (Func->allocate<Variable>()) Variable(kVariable, Ty, Index); | 423 return new (Func->allocate<Variable>()) Variable(kVariable, Ty, Index); |
| 423 } | 424 } |
| 424 | 425 |
| 425 SizeT getIndex() const { return Number; } | 426 SizeT getIndex() const { return Number; } |
| 426 IceString getName(const Cfg *Func) const; | 427 IceString getName(const Cfg *Func) const; |
| 427 void setName(Cfg *Func, const IceString &NewName) { | 428 virtual void setName(Cfg *Func, const IceString &NewName) { |
| 428 // Make sure that the name can only be set once. | 429 // Make sure that the name can only be set once. |
| 429 assert(NameIndex == Cfg::IdentifierIndexInvalid); | 430 assert(NameIndex == Cfg::IdentifierIndexInvalid); |
| 430 if (!NewName.empty()) | 431 if (!NewName.empty()) |
| 431 NameIndex = Func->addIdentifierName(NewName); | 432 NameIndex = Func->addIdentifierName(NewName); |
| 432 } | 433 } |
| 433 | 434 |
| 434 bool getIsArg() const { return IsArgument; } | 435 bool getIsArg() const { return IsArgument; } |
| 435 void setIsArg(bool Val = true) { IsArgument = Val; } | 436 virtual void setIsArg(bool Val = true) { IsArgument = Val; } |
| 436 bool getIsImplicitArg() const { return IsImplicitArgument; } | 437 bool getIsImplicitArg() const { return IsImplicitArgument; } |
| 437 void setIsImplicitArg(bool Val = true) { IsImplicitArgument = Val; } | 438 void setIsImplicitArg(bool Val = true) { IsImplicitArgument = Val; } |
| 438 | 439 |
| 439 void setIgnoreLiveness() { IgnoreLiveness = true; } | 440 void setIgnoreLiveness() { IgnoreLiveness = true; } |
| 440 bool getIgnoreLiveness() const { return IgnoreLiveness; } | 441 bool getIgnoreLiveness() const { return IgnoreLiveness; } |
| 441 | 442 |
| 442 int32_t getStackOffset() const { return StackOffset; } | 443 int32_t getStackOffset() const { return StackOffset; } |
| 443 void setStackOffset(int32_t Offset) { StackOffset = Offset; } | 444 void setStackOffset(int32_t Offset) { StackOffset = Offset; } |
| 444 | 445 |
| 445 static const int32_t NoRegister = -1; | 446 static const int32_t NoRegister = -1; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 478 } | 479 } |
| 479 bool rangeOverlaps(const Variable *Other) const { | 480 bool rangeOverlaps(const Variable *Other) const { |
| 480 const bool UseTrimmed = true; | 481 const bool UseTrimmed = true; |
| 481 return Live.overlaps(Other->Live, UseTrimmed); | 482 return Live.overlaps(Other->Live, UseTrimmed); |
| 482 } | 483 } |
| 483 bool rangeOverlapsStart(const Variable *Other) const { | 484 bool rangeOverlapsStart(const Variable *Other) const { |
| 484 const bool UseTrimmed = true; | 485 const bool UseTrimmed = true; |
| 485 return Live.overlapsInst(Other->Live.getStart(), UseTrimmed); | 486 return Live.overlapsInst(Other->Live.getStart(), UseTrimmed); |
| 486 } | 487 } |
| 487 | 488 |
| 488 Variable *getLo() const { return LoVar; } | |
| 489 Variable *getHi() const { return HiVar; } | |
| 490 void setLoHi(Variable *Lo, Variable *Hi) { | |
| 491 assert(LoVar == nullptr); | |
| 492 assert(HiVar == nullptr); | |
| 493 LoVar = Lo; | |
| 494 HiVar = Hi; | |
| 495 } | |
| 496 /// Creates a temporary copy of the variable with a different type. Used | 489 /// Creates a temporary copy of the variable with a different type. Used |
| 497 /// primarily for syntactic correctness of textual assembly emission. Note | 490 /// primarily for syntactic correctness of textual assembly emission. Note |
| 498 /// that only basic information is copied, in particular not IsArgument, | 491 /// that only basic information is copied, in particular not IsArgument, |
| 499 /// IsImplicitArgument, IgnoreLiveness, RegNumTmp, Live, LoVar, HiVar, | 492 /// IsImplicitArgument, IgnoreLiveness, RegNumTmp, Live, LoVar, HiVar, |
| 500 /// VarsReal. | 493 /// VarsReal. |
| 501 Variable *asType(Type Ty); | 494 Variable *asType(Type Ty); |
| 502 | 495 |
| 503 void emit(const Cfg *Func) const override; | 496 void emit(const Cfg *Func) const override; |
| 504 using Operand::dump; | 497 using Operand::dump; |
| 505 void dump(const Cfg *Func, Ostream &Str) const override; | 498 void dump(const Cfg *Func, Ostream &Str) const override; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 522 /// Number is unique across all variables, and is used as a (bit)vector index | 515 /// Number is unique across all variables, and is used as a (bit)vector index |
| 523 /// for liveness analysis. | 516 /// for liveness analysis. |
| 524 const SizeT Number; | 517 const SizeT Number; |
| 525 Cfg::IdentifierIndexType NameIndex = Cfg::IdentifierIndexInvalid; | 518 Cfg::IdentifierIndexType NameIndex = Cfg::IdentifierIndexInvalid; |
| 526 bool IsArgument = false; | 519 bool IsArgument = false; |
| 527 bool IsImplicitArgument = false; | 520 bool IsImplicitArgument = false; |
| 528 /// IgnoreLiveness means that the variable should be ignored when constructing | 521 /// IgnoreLiveness means that the variable should be ignored when constructing |
| 529 /// and validating live ranges. This is usually reserved for the stack | 522 /// and validating live ranges. This is usually reserved for the stack |
| 530 /// pointer. | 523 /// pointer. |
| 531 bool IgnoreLiveness = false; | 524 bool IgnoreLiveness = false; |
| 532 /// StackOffset is the canonical location on stack (only if RegNum==NoRegister | 525 RegRequirement RegRequirement = RR_MayHaveRegister; |
| 533 /// || IsArgument). | |
| 534 int32_t StackOffset = 0; | |
| 535 /// RegNum is the allocated register, or NoRegister if it isn't | 526 /// RegNum is the allocated register, or NoRegister if it isn't |
| 536 /// register-allocated. | 527 /// register-allocated. |
| 537 int32_t RegNum = NoRegister; | 528 int32_t RegNum = NoRegister; |
| 538 /// RegNumTmp is the tentative assignment during register allocation. | 529 /// RegNumTmp is the tentative assignment during register allocation. |
| 539 int32_t RegNumTmp = NoRegister; | 530 int32_t RegNumTmp = NoRegister; |
| 540 RegRequirement RegRequirement = RR_MayHaveRegister; | 531 /// StackOffset is the canonical location on stack (only if |
| 532 /// RegNum==NoRegister || IsArgument). |
| 533 int32_t StackOffset = 0; |
| 541 LiveRange Live; | 534 LiveRange Live; |
| 542 // LoVar and HiVar are needed for lowering from 64 to 32 bits. When lowering | 535 /// VarsReal (and Operand::Vars) are set up such that Vars[0] == this. |
| 543 // from I64 to I32 on a 32-bit architecture, we split the variable into two | 536 Variable *VarsReal[1]; |
| 544 // machine-size pieces. LoVar is the low-order machine-size portion, and | 537 }; |
| 545 // HiVar is the remaining high-order portion. | 538 |
| 546 // TODO: It's wasteful to penalize all variables on all targets this way; use | 539 // Variable64On32 represents a 64-bit variable on a 32-bit architecture. In |
| 547 // a sparser representation. It's also wasteful for a 64-bit target. | 540 // this situation the variable must be split into a low and a high word. |
| 541 class Variable64On32 : public Variable { |
| 542 Variable64On32() = delete; |
| 543 Variable64On32(const Variable64On32 &) = delete; |
| 544 Variable64On32 &operator=(const Variable64On32 &) = delete; |
| 545 |
| 546 public: |
| 547 static Variable64On32 *create(Cfg *Func, Type Ty, SizeT Index) { |
| 548 return new (Func->allocate<Variable64On32>()) Variable64On32( |
| 549 kVariable64On32, Ty, Index); |
| 550 } |
| 551 |
| 552 void setName(Cfg *Func, const IceString &NewName) override { |
| 553 Variable::setName(Func, NewName); |
| 554 if (LoVar && HiVar) { |
| 555 LoVar->setName(Func, getName(Func) + "__lo"); |
| 556 HiVar->setName(Func, getName(Func) + "__hi"); |
| 557 } |
| 558 } |
| 559 |
| 560 void setIsArg(bool Val = true) override { |
| 561 Variable::setIsArg(Val); |
| 562 if (LoVar && HiVar) { |
| 563 LoVar->setIsArg(Val); |
| 564 HiVar->setIsArg(Val); |
| 565 } |
| 566 } |
| 567 |
| 568 Variable *getLo() const { |
| 569 assert(LoVar != nullptr); |
| 570 return LoVar; |
| 571 } |
| 572 Variable *getHi() const { |
| 573 assert(HiVar != nullptr); |
| 574 return HiVar; |
| 575 } |
| 576 |
| 577 void initHiLo(Cfg *Func) { |
| 578 assert(LoVar == nullptr); |
| 579 assert(HiVar == nullptr); |
| 580 LoVar = Func->makeVariable(IceType_i32); |
| 581 HiVar = Func->makeVariable(IceType_i32); |
| 582 LoVar->setIsArg(getIsArg()); |
| 583 HiVar->setIsArg(getIsArg()); |
| 584 LoVar->setName(Func, getName(Func) + "__lo"); |
| 585 HiVar->setName(Func, getName(Func) + "__hi"); |
| 586 } |
| 587 |
| 588 static bool classof(const Operand *Operand) { |
| 589 OperandKind Kind = Operand->getKind(); |
| 590 return Kind == kVariable64On32; |
| 591 } |
| 592 |
| 593 protected: |
| 594 Variable64On32(OperandKind K, Type Ty, SizeT Index) |
| 595 : Variable(K, Ty, Index) { |
| 596 assert(typeWidthInBytes(Ty) == 8); |
| 597 } |
| 598 |
| 548 Variable *LoVar = nullptr; | 599 Variable *LoVar = nullptr; |
| 549 Variable *HiVar = nullptr; | 600 Variable *HiVar = nullptr; |
| 550 /// VarsReal (and Operand::Vars) are set up such that Vars[0] == this. | |
| 551 Variable *VarsReal[1]; | |
| 552 }; | 601 }; |
| 553 | 602 |
| 554 enum MetadataKind { | 603 enum MetadataKind { |
| 555 VMK_Uses, /// Track only uses, not defs | 604 VMK_Uses, /// Track only uses, not defs |
| 556 VMK_SingleDefs, /// Track uses+defs, but only record single def | 605 VMK_SingleDefs, /// Track uses+defs, but only record single def |
| 557 VMK_All /// Track uses+defs, including full def list | 606 VMK_All /// Track uses+defs, including full def list |
| 558 }; | 607 }; |
| 559 using InstDefList = CfgVector<const Inst *>; | 608 using InstDefList = CfgVector<const Inst *>; |
| 560 | 609 |
| 561 /// VariableTracking tracks the metadata for a single variable. It is | 610 /// VariableTracking tracks the metadata for a single variable. It is |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 652 private: | 701 private: |
| 653 const Cfg *Func; | 702 const Cfg *Func; |
| 654 MetadataKind Kind; | 703 MetadataKind Kind; |
| 655 CfgVector<VariableTracking> Metadata; | 704 CfgVector<VariableTracking> Metadata; |
| 656 const static InstDefList NoDefinitions; | 705 const static InstDefList NoDefinitions; |
| 657 }; | 706 }; |
| 658 | 707 |
| 659 } // end of namespace Ice | 708 } // end of namespace Ice |
| 660 | 709 |
| 661 #endif // SUBZERO_SRC_ICEOPERAND_H | 710 #endif // SUBZERO_SRC_ICEOPERAND_H |
| OLD | NEW |