/// 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);
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;
}
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 << ":";
/// 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;
/// 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;
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
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 {
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 {
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;
// 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;
}
// 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;
// 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,
// 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;