Subzero: Merge SpillVariable functionality directly into Variable.
Specifically, this is the ability to link variable B to variable A, such that if neither A nor B get a register assignment, they share a stack slot.
This CL just refactors and keeps basically the same functionality, in preparation for new work on variable splitting.
BUG= none
R=jpp@chromium.org
Review URL: https://codereview.chromium.org/2107073002 .
diff --git a/src/IceCfg.h b/src/IceCfg.h
index 181585f..42e6ef1 100644
--- a/src/IceCfg.h
+++ b/src/IceCfg.h
@@ -111,8 +111,8 @@
/// Create a new Variable with a particular type and an optional name. The
/// Node argument is the node where the variable is defined.
- // TODO(jpp): untemplate this with separate methods: makeVariable,
- // makeSpillVariable, and makeStackVariable.
+ // TODO(jpp): untemplate this with separate methods: makeVariable and
+ // makeStackVariable.
template <typename T = Variable> T *makeVariable(Type Ty) {
SizeT Index = Variables.size();
auto *Var = T::create(this, Ty, Index);
diff --git a/src/IceOperand.cpp b/src/IceOperand.cpp
index 50d70b9..e6593c7 100644
--- a/src/IceOperand.cpp
+++ b/src/IceOperand.cpp
@@ -198,11 +198,12 @@
if (!BuildDefs::dump() || getType() == Ty)
return this;
static constexpr SizeT One = 1;
- Variable *V = new (CfgLocalAllocator<Variable>().allocate(One))
+ auto *V = new (CfgLocalAllocator<Variable>().allocate(One))
Variable(Func, kVariable, Ty, Number);
V->Name = Name;
V->RegNum = NewRegNum.hasValue() ? NewRegNum : RegNum;
V->StackOffset = StackOffset;
+ V->LinkedTo = LinkedTo;
return V;
}
@@ -537,8 +538,11 @@
return;
}
if (Func->isVerbose(IceV_RegOrigins) ||
- (!hasReg() && !Func->getTarget()->hasComputedFrame()))
+ (!hasReg() && !Func->getTarget()->hasComputedFrame())) {
Str << "%" << getName();
+ if (getLinkedTo() != nullptr)
+ Str << ":%" << getLinkedTo()->getName();
+ }
if (hasReg()) {
if (Func->isVerbose(IceV_RegOrigins))
Str << ":";
diff --git a/src/IceOperand.h b/src/IceOperand.h
index d29d25e..29d27a2 100644
--- a/src/IceOperand.h
+++ b/src/IceOperand.h
@@ -656,7 +656,7 @@
/// Variable represents an operand that is register-allocated or
/// stack-allocated. If it is register-allocated, it will ultimately have a
-/// non-negative RegNum field.
+/// valid RegNum field.
class Variable : public Operand {
Variable() = delete;
Variable(const Variable &) = delete;
@@ -773,6 +773,23 @@
/// Return reg num of base register, if different from stack/frame register.
virtual RegNumT getBaseRegNum() const { return RegNumT(); }
+ void setLinkedTo(const Variable *Var) {
+ // If B is linked to A, and we now want to link C to B, we instead link C to
+ // A so that we have one root (A) and all leaves (B, C) link directly to the
+ // root.
+ if (Var->getLinkedTo() != nullptr) {
+ Var = Var->LinkedTo;
+ assert(Var->LinkedTo == nullptr);
+ }
+ LinkedTo = Var;
+ }
+ const Variable *getLinkedTo() const {
+ // Make sure a leaf links directly to the root.
+ if (LinkedTo != nullptr)
+ assert(LinkedTo->LinkedTo == nullptr);
+ return LinkedTo;
+ }
+
static bool classof(const Operand *Operand) {
OperandKind Kind = Operand->getKind();
return Kind >= kVariable && Kind <= kVariable_Max;
@@ -814,6 +831,9 @@
LiveRange Live;
/// VarsReal (and Operand::Vars) are set up such that Vars[0] == this.
Variable *VarsReal[1];
+ /// This Variable may be "linked" to another Variable, such that if neither
+ /// Variable gets a register, they are guaranteed to share a stack location.
+ const Variable *LinkedTo = nullptr;
};
// Variable64On32 represents a 64-bit variable on a 32-bit architecture. In
diff --git a/src/IceTargetLoweringX8632Traits.h b/src/IceTargetLoweringX8632Traits.h
index 2716a34..518ac3e 100644
--- a/src/IceTargetLoweringX8632Traits.h
+++ b/src/IceTargetLoweringX8632Traits.h
@@ -933,36 +933,6 @@
Portion Part;
};
- /// SpillVariable decorates a Variable by linking it to another Variable. When
- /// stack frame offsets are computed, the SpillVariable is given a distinct
- /// stack slot only if its linked Variable has a register. If the linked
- /// Variable has a stack slot, then the Variable and SpillVariable share that
- /// slot.
- class SpillVariable : public Variable {
- SpillVariable() = delete;
- SpillVariable(const SpillVariable &) = delete;
- SpillVariable &operator=(const SpillVariable &) = delete;
-
- public:
- static SpillVariable *create(Cfg *Func, Type Ty, SizeT Index) {
- return new (Func->allocate<SpillVariable>())
- SpillVariable(Func, Ty, Index);
- }
- constexpr static auto SpillVariableKind =
- static_cast<OperandKind>(kVariable_Target);
- static bool classof(const Operand *Operand) {
- return Operand->getKind() == SpillVariableKind;
- }
- void setLinkedTo(Variable *Var) { LinkedTo = Var; }
- Variable *getLinkedTo() const { return LinkedTo; }
- // Inherit dump() and emit() from Variable.
-
- private:
- SpillVariable(const Cfg *Func, Type Ty, SizeT Index)
- : Variable(Func, SpillVariableKind, Ty, Index), LinkedTo(nullptr) {}
- Variable *LinkedTo;
- };
-
// Note: The following data structures are defined in IceInstX8632.cpp.
static const struct InstBrAttributesType {
diff --git a/src/IceTargetLoweringX8664Traits.h b/src/IceTargetLoweringX8664Traits.h
index 4e9173a..573c263 100644
--- a/src/IceTargetLoweringX8664Traits.h
+++ b/src/IceTargetLoweringX8664Traits.h
@@ -978,36 +978,6 @@
Portion Part;
};
- /// SpillVariable decorates a Variable by linking it to another Variable. When
- /// stack frame offsets are computed, the SpillVariable is given a distinct
- /// stack slot only if its linked Variable has a register. If the linked
- /// Variable has a stack slot, then the Variable and SpillVariable share that
- /// slot.
- class SpillVariable : public Variable {
- SpillVariable() = delete;
- SpillVariable(const SpillVariable &) = delete;
- SpillVariable &operator=(const SpillVariable &) = delete;
-
- public:
- static SpillVariable *create(Cfg *Func, Type Ty, SizeT Index) {
- return new (Func->allocate<SpillVariable>())
- SpillVariable(Func, Ty, Index);
- }
- constexpr static auto SpillVariableKind =
- static_cast<OperandKind>(kVariable_Target);
- static bool classof(const Operand *Operand) {
- return Operand->getKind() == SpillVariableKind;
- }
- void setLinkedTo(Variable *Var) { LinkedTo = Var; }
- Variable *getLinkedTo() const { return LinkedTo; }
- // Inherit dump() and emit() from Variable.
-
- private:
- SpillVariable(const Cfg *Func, Type Ty, SizeT Index)
- : Variable(Func, SpillVariableKind, Ty, Index), LinkedTo(nullptr) {}
- Variable *LinkedTo;
- };
-
// Note: The following data structures are defined in IceInstX8664.cpp.
static const struct InstBrAttributesType {
diff --git a/src/IceTargetLoweringX86Base.h b/src/IceTargetLoweringX86Base.h
index d465423..b1b2b82 100644
--- a/src/IceTargetLoweringX86Base.h
+++ b/src/IceTargetLoweringX86Base.h
@@ -70,7 +70,6 @@
using X86Operand = typename Traits::X86Operand;
using X86OperandMem = typename Traits::X86OperandMem;
using SegmentRegisters = typename Traits::X86OperandMem::SegmentRegisters;
- using SpillVariable = typename Traits::SpillVariable;
using InstX86Br = typename Traits::Insts::Br;
using InstX86FakeRMW = typename Traits::Insts::FakeRMW;
diff --git a/src/IceTargetLoweringX86BaseImpl.h b/src/IceTargetLoweringX86BaseImpl.h
index 09bce6d..a9dc7a7 100644
--- a/src/IceTargetLoweringX86BaseImpl.h
+++ b/src/IceTargetLoweringX86BaseImpl.h
@@ -1043,10 +1043,11 @@
// stack slot.
std::function<bool(Variable *)> TargetVarHook =
[&VariablesLinkedToSpillSlots](Variable *Var) {
- if (auto *SpillVar =
- llvm::dyn_cast<typename Traits::SpillVariable>(Var)) {
+ if (Var->getLinkedTo() != nullptr) {
+ // TODO(stichnot): This assert won't necessarily be true in the
+ // future.
assert(Var->mustNotHaveReg());
- if (SpillVar->getLinkedTo() && !SpillVar->getLinkedTo()->hasReg()) {
+ if (!Var->getLinkedTo()->hasReg()) {
VariablesLinkedToSpillSlots.push_back(Var);
return true;
}
@@ -1210,8 +1211,8 @@
// Assign stack offsets to variables that have been linked to spilled
// variables.
for (Variable *Var : VariablesLinkedToSpillSlots) {
- Variable *Linked =
- (llvm::cast<typename Traits::SpillVariable>(Var))->getLinkedTo();
+ const Variable *Linked = Var->getLinkedTo();
+ assert(Linked != nullptr);
Var->setStackOffset(Linked->getStackOffset());
}
this->HasComputedFrame = true;
@@ -3086,10 +3087,8 @@
// a_hi.i32 = t_hi.i32
Operand *SpillLo, *SpillHi;
if (auto *Src0Var = llvm::dyn_cast<Variable>(Src0RM)) {
- SpillVariable *SpillVar =
- Func->makeVariable<SpillVariable>(IceType_f64);
- SpillVar->setLinkedTo(Src0Var);
- Variable *Spill = SpillVar;
+ Variable *Spill = Func->makeVariable(IceType_f64);
+ Spill->setLinkedTo(Src0Var);
Spill->setMustNotHaveReg();
_movq(Spill, Src0RM);
SpillLo = Traits::VariableSplit::create(Func, Spill,
@@ -3134,10 +3133,8 @@
// t_hi.i32 = b_hi.i32
// hi(s.f64) = t_hi.i32
// a.f64 = s.f64
- SpillVariable *SpillVar =
- Func->makeVariable<SpillVariable>(IceType_f64);
- SpillVar->setLinkedTo(Dest);
- Variable *Spill = SpillVar;
+ Variable *Spill = Func->makeVariable(IceType_f64);
+ Spill->setLinkedTo(Dest);
Spill->setMustNotHaveReg();
Variable *T_Lo = nullptr, *T_Hi = nullptr;