OSDN Git Service

Subzero: Merge SpillVariable functionality directly into Variable.
authorJim Stichnoth <stichnot@chromium.org>
Wed, 29 Jun 2016 04:40:33 +0000 (21:40 -0700)
committerJim Stichnoth <stichnot@chromium.org>
Wed, 29 Jun 2016 04:40:33 +0000 (21:40 -0700)
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 .

src/IceCfg.h
src/IceOperand.cpp
src/IceOperand.h
src/IceTargetLoweringX8632Traits.h
src/IceTargetLoweringX8664Traits.h
src/IceTargetLoweringX86Base.h
src/IceTargetLoweringX86BaseImpl.h

index 181585f..42e6ef1 100644 (file)
@@ -111,8 +111,8 @@ public:
 
   /// 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);
index 50d70b9..e6593c7 100644 (file)
@@ -198,11 +198,12 @@ const Variable *Variable::asType(const Cfg *Func, Type Ty,
   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 @@ void Variable::dump(const Cfg *Func, Ostream &Str) const {
     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 << ":";
index d29d25e..29d27a2 100644 (file)
@@ -656,7 +656,7 @@ Ostream &operator<<(Ostream &Str, const LiveRange &L);
 
 /// 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 @@ public:
   /// 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 @@ protected:
   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
index 2716a34..518ac3e 100644 (file)
@@ -933,36 +933,6 @@ public:
     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 {
index 4e9173a..573c263 100644 (file)
@@ -978,36 +978,6 @@ public:
     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 {
index d465423..b1b2b82 100644 (file)
@@ -70,7 +70,6 @@ public:
   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;
index 09bce6d..a9dc7a7 100644 (file)
@@ -1043,10 +1043,11 @@ void TargetX86Base<TraitsType>::addProlog(CfgNode *Node) {
   // 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 @@ void TargetX86Base<TraitsType>::addProlog(CfgNode *Node) {
   // 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 @@ void TargetX86Base<TraitsType>::lowerCast(const InstCast *Instr) {
         //   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 @@ void TargetX86Base<TraitsType>::lowerCast(const InstCast *Instr) {
         //   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;