Refactor Hi and Lo out of Variable.
BUG=
R=stichnot@chromium.org
Review URL: https://codereview.chromium.org/1326013002 .
diff --git a/src/IceOperand.h b/src/IceOperand.h
index 67b1d23..94bc8ab 100644
--- a/src/IceOperand.h
+++ b/src/IceOperand.h
@@ -43,6 +43,7 @@
kConst_Target, // leave space for target-specific constant kinds
kConst_Max = kConst_Target + MaxTargetKinds,
kVariable,
+ kVariable64On32,
kVariable_Target, // leave space for target-specific variable kinds
kVariable_Max = kVariable_Target + MaxTargetKinds,
// Target-specific operand classes use kTarget as the starting point for
@@ -411,7 +412,7 @@
Variable(const Variable &) = delete;
Variable &operator=(const Variable &) = delete;
- enum RegRequirement {
+ enum RegRequirement : uint8_t {
RR_MayHaveRegister,
RR_MustHaveRegister,
RR_MustNotHaveRegister,
@@ -424,7 +425,7 @@
SizeT getIndex() const { return Number; }
IceString getName(const Cfg *Func) const;
- void setName(Cfg *Func, const IceString &NewName) {
+ virtual void setName(Cfg *Func, const IceString &NewName) {
// Make sure that the name can only be set once.
assert(NameIndex == Cfg::IdentifierIndexInvalid);
if (!NewName.empty())
@@ -432,7 +433,7 @@
}
bool getIsArg() const { return IsArgument; }
- void setIsArg(bool Val = true) { IsArgument = Val; }
+ virtual void setIsArg(bool Val = true) { IsArgument = Val; }
bool getIsImplicitArg() const { return IsImplicitArgument; }
void setIsImplicitArg(bool Val = true) { IsImplicitArgument = Val; }
@@ -485,14 +486,6 @@
return Live.overlapsInst(Other->Live.getStart(), UseTrimmed);
}
- Variable *getLo() const { return LoVar; }
- Variable *getHi() const { return HiVar; }
- void setLoHi(Variable *Lo, Variable *Hi) {
- assert(LoVar == nullptr);
- assert(HiVar == nullptr);
- LoVar = Lo;
- HiVar = Hi;
- }
/// Creates a temporary copy of the variable with a different type. Used
/// primarily for syntactic correctness of textual assembly emission. Note
/// that only basic information is copied, in particular not IsArgument,
@@ -529,28 +522,84 @@
/// and validating live ranges. This is usually reserved for the stack
/// pointer.
bool IgnoreLiveness = false;
- /// StackOffset is the canonical location on stack (only if RegNum==NoRegister
- /// || IsArgument).
- int32_t StackOffset = 0;
+ RegRequirement RegRequirement = RR_MayHaveRegister;
/// RegNum is the allocated register, or NoRegister if it isn't
/// register-allocated.
int32_t RegNum = NoRegister;
/// RegNumTmp is the tentative assignment during register allocation.
int32_t RegNumTmp = NoRegister;
- RegRequirement RegRequirement = RR_MayHaveRegister;
+ /// StackOffset is the canonical location on stack (only if
+ /// RegNum==NoRegister || IsArgument).
+ int32_t StackOffset = 0;
LiveRange Live;
- // LoVar and HiVar are needed for lowering from 64 to 32 bits. When lowering
- // from I64 to I32 on a 32-bit architecture, we split the variable into two
- // machine-size pieces. LoVar is the low-order machine-size portion, and
- // HiVar is the remaining high-order portion.
- // TODO: It's wasteful to penalize all variables on all targets this way; use
- // a sparser representation. It's also wasteful for a 64-bit target.
- Variable *LoVar = nullptr;
- Variable *HiVar = nullptr;
/// VarsReal (and Operand::Vars) are set up such that Vars[0] == this.
Variable *VarsReal[1];
};
+// Variable64On32 represents a 64-bit variable on a 32-bit architecture. In
+// this situation the variable must be split into a low and a high word.
+class Variable64On32 : public Variable {
+ Variable64On32() = delete;
+ Variable64On32(const Variable64On32 &) = delete;
+ Variable64On32 &operator=(const Variable64On32 &) = delete;
+
+public:
+ static Variable64On32 *create(Cfg *Func, Type Ty, SizeT Index) {
+ return new (Func->allocate<Variable64On32>()) Variable64On32(
+ kVariable64On32, Ty, Index);
+ }
+
+ void setName(Cfg *Func, const IceString &NewName) override {
+ Variable::setName(Func, NewName);
+ if (LoVar && HiVar) {
+ LoVar->setName(Func, getName(Func) + "__lo");
+ HiVar->setName(Func, getName(Func) + "__hi");
+ }
+ }
+
+ void setIsArg(bool Val = true) override {
+ Variable::setIsArg(Val);
+ if (LoVar && HiVar) {
+ LoVar->setIsArg(Val);
+ HiVar->setIsArg(Val);
+ }
+ }
+
+ Variable *getLo() const {
+ assert(LoVar != nullptr);
+ return LoVar;
+ }
+ Variable *getHi() const {
+ assert(HiVar != nullptr);
+ return HiVar;
+ }
+
+ void initHiLo(Cfg *Func) {
+ assert(LoVar == nullptr);
+ assert(HiVar == nullptr);
+ LoVar = Func->makeVariable(IceType_i32);
+ HiVar = Func->makeVariable(IceType_i32);
+ LoVar->setIsArg(getIsArg());
+ HiVar->setIsArg(getIsArg());
+ LoVar->setName(Func, getName(Func) + "__lo");
+ HiVar->setName(Func, getName(Func) + "__hi");
+ }
+
+ static bool classof(const Operand *Operand) {
+ OperandKind Kind = Operand->getKind();
+ return Kind == kVariable64On32;
+ }
+
+protected:
+ Variable64On32(OperandKind K, Type Ty, SizeT Index)
+ : Variable(K, Ty, Index) {
+ assert(typeWidthInBytes(Ty) == 8);
+ }
+
+ Variable *LoVar = nullptr;
+ Variable *HiVar = nullptr;
+};
+
enum MetadataKind {
VMK_Uses, /// Track only uses, not defs
VMK_SingleDefs, /// Track uses+defs, but only record single def