Subzero: Refactor tracking of Defs and block-local Variables.

This affects tracking of two kinds of Variable metadata: whether a
Variable is block-local (i.e., all uses are in a single block) and if
so, which CfgNode that is; and whether a Variable has a single defining
instruction, and if so, which Inst that is.

Originally, this metadata was constructed incrementally, which was
quite fragile and most likely inaccurate under many circumstances.

In the new approach, this metadata is reconstructed in a separate pass
as needed.

As a side benefit, the metadata fields are removed from each Variable
and pulled into a separate structure, shrinking the size of Variable.

There should be no functional changes, except that simple stack slot
coalescing is turned off under Om1, since it takes a separate pass to
calculate block-local variables, and passes are minimized under Om1.
As a result, a couple of the lit tests needed to be changed.

There are a few non-mechanical changes, generally to tighten up
Variable tracking for liveness analysis.

This is being done mainly to get precise Variable definition
information so that register allocation can infer the best register
preferences as well as when overlapping live ranges are allowable.

BUG=none
R=jvoung@chromium.org

Review URL: https://codereview.chromium.org/589003002
diff --git a/src/IceCfg.cpp b/src/IceCfg.cpp
index a08bebb..e1255df 100644
--- a/src/IceCfg.cpp
+++ b/src/IceCfg.cpp
@@ -28,7 +28,7 @@
       IsInternalLinkage(false), HasError(false), ErrorMessage(""), Entry(NULL),
       NextInstNumber(1), Live(NULL),
       Target(TargetLowering::createLowering(Ctx->getTargetArch(), this)),
-      CurrentNode(NULL) {}
+      VMetadata(new VariablesMetadata(this)), CurrentNode(NULL) {}
 
 Cfg::~Cfg() {}
 
@@ -45,16 +45,20 @@
   return Node;
 }
 
-Variable *Cfg::makeVariable(Type Ty, const CfgNode *Node,
-                            const IceString &Name) {
-  return makeVariable<Variable>(Ty, Node, Name);
+Variable *Cfg::makeVariable(Type Ty, const IceString &Name) {
+  return makeVariable<Variable>(Ty, Name);
 }
 
 void Cfg::addArg(Variable *Arg) {
-  Arg->setIsArg(this);
+  Arg->setIsArg();
   Args.push_back(Arg);
 }
 
+void Cfg::addImplicitArg(Variable *Arg) {
+  Arg->setIsImplicitArg();
+  ImplicitArgs.push_back(Arg);
+}
+
 // Returns whether the stack frame layout has been computed yet.  This
 // is used for dumping the stack frame location of Variables.
 bool Cfg::hasComputedFrame() const { return getTarget()->hasComputedFrame(); }
@@ -147,6 +151,7 @@
 // completely with a single block.  It is a quick single pass and
 // doesn't need to iterate until convergence.
 void Cfg::livenessLightweight() {
+  getVMetadata()->init();
   for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
     (*I)->livenessLightweight();
   }
@@ -154,6 +159,7 @@
 
 void Cfg::liveness(LivenessMode Mode) {
   Live.reset(new Liveness(this, Mode));
+  getVMetadata()->init();
   Live->init();
   // Initialize with all nodes needing to be processed.
   llvm::BitVector NeedToProcess(Nodes.size(), true);
@@ -361,9 +367,12 @@
     for (VarList::const_iterator I = Variables.begin(), E = Variables.end();
          I != E; ++I) {
       Variable *Var = *I;
-      Str << "//"
-          << " multiblock=" << Var->isMultiblockLife() << " "
-          << " weight=" << Var->getWeight() << " ";
+      Str << "// multiblock=";
+      if (getVMetadata()->isTracked(Var))
+        Str << getVMetadata()->isMultiBlock(Var);
+      else
+        Str << "?";
+      Str << " weight=" << Var->getWeight() << " ";
       Var->dump(this);
       if (Variable *Pref = Var->getPreferredRegister()) {
         Str << " pref=";
diff --git a/src/IceCfg.h b/src/IceCfg.h
index 7a265ad..73dd814 100644
--- a/src/IceCfg.h
+++ b/src/IceCfg.h
@@ -63,17 +63,15 @@
   // Manage Variables.
   // Create a new Variable with a particular type and an optional
   // name.  The Node argument is the node where the variable is defined.
-  template <typename T>
-  T *makeVariable(Type Ty, const CfgNode *Node, const IceString &Name = "") {
+  template <typename T> T *makeVariable(Type Ty, const IceString &Name = "") {
     SizeT Index = Variables.size();
-    T *Var = T::create(this, Ty, Node, Index, Name);
+    T *Var = T::create(this, Ty, Index, Name);
     Variables.push_back(Var);
     return Var;
   }
   // TODO(stichnot): Remove this function with C++11, and use default
   // argument <typename T=Variable> above.
-  Variable *makeVariable(Type Ty, const CfgNode *Node,
-                         const IceString &Name = "");
+  Variable *makeVariable(Type Ty, const IceString &Name = "");
   SizeT getNumVariables() const { return Variables.size(); }
   const VarList &getVariables() const { return Variables; }
 
@@ -81,9 +79,12 @@
   void addArg(Variable *Arg);
   const VarList &getArgs() const { return Args; }
   VarList &getArgs() { return Args; }
+  void addImplicitArg(Variable *Arg);
+  const VarList &getImplicitArgs() const { return ImplicitArgs; }
 
   // Miscellaneous accessors.
   TargetLowering *getTarget() const { return Target.get(); }
+  VariablesMetadata *getVMetadata() const { return VMetadata.get(); }
   Liveness *getLiveness() const { return Live.get(); }
   bool hasComputedFrame() const;
 
@@ -161,8 +162,10 @@
   InstNumberT NextInstNumber;
   VarList Variables;
   VarList Args; // subset of Variables, in argument order
+  VarList ImplicitArgs; // subset of Variables
   llvm::OwningPtr<Liveness> Live;
   llvm::OwningPtr<TargetLowering> Target;
+  llvm::OwningPtr<VariablesMetadata> VMetadata;
 
   // CurrentNode is maintained during dumping/emitting just for
   // validating Variable::DefNode.  Normally, a traversal over
diff --git a/src/IceCfgNode.cpp b/src/IceCfgNode.cpp
index 2b05e58..3277564 100644
--- a/src/IceCfgNode.cpp
+++ b/src/IceCfgNode.cpp
@@ -47,7 +47,6 @@
   } else {
     Insts.push_back(Inst);
   }
-  Inst->updateVars(this);
 }
 
 // Renumbers the non-deleted instructions in the node.  This needs to
@@ -92,9 +91,8 @@
 // blocks.  Note that this transformation preserves SSA form.
 void CfgNode::placePhiLoads() {
   for (PhiList::iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) {
-    Inst *Inst = (*I)->lower(Func, this);
+    Inst *Inst = (*I)->lower(Func);
     Insts.insert(Insts.begin(), Inst);
-    Inst->updateVars(this);
   }
 }
 
@@ -213,7 +211,6 @@
         Insts.insert(SafeInsertionPoint, NewInst);
       else
         Insts.insert(InsertionPoint, NewInst);
-      NewInst->updateVars(this);
     }
   }
 }
@@ -281,12 +278,12 @@
        I != E; ++I) {
     if ((*I)->isDeleted())
       continue;
-    (*I)->livenessLightweight(Live);
+    (*I)->livenessLightweight(Func, Live);
   }
   for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) {
     if ((*I)->isDeleted())
       continue;
-    (*I)->livenessLightweight(Live);
+    (*I)->livenessLightweight(Func, Live);
   }
 }
 
diff --git a/src/IceConverter.cpp b/src/IceConverter.cpp
index 9991ab2..4888e8f 100644
--- a/src/IceConverter.cpp
+++ b/src/IceConverter.cpp
@@ -56,7 +56,7 @@
 class LLVM2ICEConverter {
 public:
   LLVM2ICEConverter(Ice::GlobalContext *Ctx, LLVMContext &LLVMContext)
-      : Ctx(Ctx), Func(NULL), CurrentNode(NULL), TypeConverter(LLVMContext) {}
+      : Ctx(Ctx), Func(NULL), TypeConverter(LLVMContext) {}
 
   // Caller is expected to delete the returned Ice::Cfg object.
   Ice::Cfg *convertFunction(const Function *F) {
@@ -68,7 +68,6 @@
     Func->setInternal(F->hasInternalLinkage());
 
     // The initial definition/use of each arg is the entry node.
-    CurrentNode = mapBasicBlockToNode(&F->getEntryBlock());
     for (Function::const_arg_iterator ArgI = F->arg_begin(),
                                       ArgE = F->arg_end();
          ArgI != ArgE; ++ArgI) {
@@ -85,7 +84,6 @@
     }
     for (Function::const_iterator BBI = F->begin(), BBE = F->end(); BBI != BBE;
          ++BBI) {
-      CurrentNode = mapBasicBlockToNode(BBI);
       convertBasicBlock(BBI);
     }
     Func->setEntryNode(mapBasicBlockToNode(&F->getEntryBlock()));
@@ -132,8 +130,7 @@
     if (IceTy == Ice::IceType_void)
       return NULL;
     if (VarMap.find(V) == VarMap.end()) {
-      assert(CurrentNode);
-      VarMap[V] = Func->makeVariable(IceTy, CurrentNode, V->getName());
+      VarMap[V] = Func->makeVariable(IceTy, V->getName());
     }
     return VarMap[V];
   }
@@ -614,7 +611,6 @@
   // Data
   Ice::GlobalContext *Ctx;
   Ice::Cfg *Func;
-  Ice::CfgNode *CurrentNode;
   std::map<const Value *, Ice::Variable *> VarMap;
   std::map<const BasicBlock *, Ice::CfgNode *> NodeMap;
   Ice::TypeConverter TypeConverter;
diff --git a/src/IceDefs.h b/src/IceDefs.h
index 44a6132..0f200bc 100644
--- a/src/IceDefs.h
+++ b/src/IceDefs.h
@@ -57,6 +57,7 @@
 class Operand;
 class TargetLowering;
 class Variable;
+class VariablesMetadata;
 
 // TODO: Switch over to LLVM's ADT container classes.
 // http://llvm.org/docs/ProgrammersManual.html#picking-the-right-data-structure-for-a-task
diff --git a/src/IceInst.cpp b/src/IceInst.cpp
index d6e0f59..629c6bd 100644
--- a/src/IceInst.cpp
+++ b/src/IceInst.cpp
@@ -111,21 +111,7 @@
   return false;
 }
 
-void Inst::updateVars(CfgNode *Node) {
-  if (Dest)
-    Dest->setDefinition(this, Node);
-
-  for (SizeT I = 0; I < getSrcSize(); ++I) {
-    Operand *Src = getSrc(I);
-    SizeT NumVars = Src->getNumVars();
-    for (SizeT J = 0; J < NumVars; ++J) {
-      Variable *Var = Src->getVar(J);
-      Var->setUse(this, Node);
-    }
-  }
-}
-
-void Inst::livenessLightweight(llvm::BitVector &Live) {
+void Inst::livenessLightweight(Cfg *Func, llvm::BitVector &Live) {
   assert(!isDeleted());
   if (llvm::isa<InstFakeKill>(this))
     return;
@@ -136,7 +122,7 @@
     SizeT NumVars = Src->getNumVars();
     for (SizeT J = 0; J < NumVars; ++J, ++VarIndex) {
       const Variable *Var = Src->getVar(J);
-      if (Var->isMultiblockLife())
+      if (Func->getVMetadata()->isMultiBlock(Var))
         continue;
       SizeT Index = Var->getIndex();
       if (Live[Index])
@@ -354,19 +340,17 @@
 
 // Change "a=phi(...)" to "a_phi=phi(...)" and return a new
 // instruction "a=a_phi".
-Inst *InstPhi::lower(Cfg *Func, CfgNode *Node) {
+Inst *InstPhi::lower(Cfg *Func) {
   Variable *Dest = getDest();
   assert(Dest);
   IceString PhiName = Dest->getName() + "_phi";
-  Variable *NewSrc = Func->makeVariable(Dest->getType(), Node, PhiName);
-  NewSrc->setIsMultidef();
+  Variable *NewSrc = Func->makeVariable(Dest->getType(), PhiName);
   this->Dest = NewSrc;
   InstAssign *NewInst = InstAssign::create(Func, Dest, NewSrc);
   // Set Dest and NewSrc to have affinity with each other, as a hint
   // for register allocation.
   Dest->setPreferredRegister(NewSrc, false);
   NewSrc->setPreferredRegister(Dest, false);
-  Dest->replaceDefinition(NewInst, Node);
   return NewInst;
 }
 
diff --git a/src/IceInst.h b/src/IceInst.h
index cf507e6..6db4971 100644
--- a/src/IceInst.h
+++ b/src/IceInst.h
@@ -92,13 +92,7 @@
     return NodeList();
   }
 
-  // Updates the status of the Variables contained within the
-  // instruction.  In particular, it marks where the Dest variable is
-  // first assigned, and it tracks whether variables are live across
-  // basic blocks, i.e. used in a different block from their definition.
-  void updateVars(CfgNode *Node);
-
-  void livenessLightweight(llvm::BitVector &Live);
+  void livenessLightweight(Cfg *Func, llvm::BitVector &Live);
   void liveness(InstNumberT InstNumber, llvm::BitVector &Live,
                 Liveness *Liveness, const CfgNode *Node);
 
@@ -520,7 +514,7 @@
   Operand *getOperandForTarget(CfgNode *Target) const;
   void livenessPhiOperand(llvm::BitVector &Live, CfgNode *Target,
                           Liveness *Liveness);
-  Inst *lower(Cfg *Func, CfgNode *Node);
+  Inst *lower(Cfg *Func);
   virtual void dump(const Cfg *Func) const;
   static bool classof(const Inst *Inst) { return Inst->getKind() == Phi; }
 
diff --git a/src/IceInstX8632.cpp b/src/IceInstX8632.cpp
index 305be73..93c193f 100644
--- a/src/IceInstX8632.cpp
+++ b/src/IceInstX8632.cpp
@@ -95,8 +95,11 @@
   }
 }
 
-InstX8632AdjustStack::InstX8632AdjustStack(Cfg *Func, SizeT Amount)
-    : InstX8632(Func, InstX8632::Adjuststack, 0, NULL), Amount(Amount) {}
+InstX8632AdjustStack::InstX8632AdjustStack(Cfg *Func, SizeT Amount,
+                                           Variable *Esp)
+    : InstX8632(Func, InstX8632::Adjuststack, 1, Esp), Amount(Amount) {
+  addSource(Esp);
+}
 
 InstX8632Mul::InstX8632Mul(Cfg *Func, Variable *Dest, Variable *Source1,
                            Operand *Source2)
@@ -1497,8 +1500,6 @@
 
 void VariableSplit::emit(const Cfg *Func) const {
   Ostream &Str = Func->getContext()->getStrEmit();
-  assert(Var->getLocalUseNode() == NULL ||
-         Var->getLocalUseNode() == Func->getCurrentNode());
   assert(!Var->hasReg());
   // The following is copied/adapted from TargetX8632::emitVariable().
   const TargetLowering *Target = Func->getTarget();
diff --git a/src/IceInstX8632.h b/src/IceInstX8632.h
index ac39170..7ab8592 100644
--- a/src/IceInstX8632.h
+++ b/src/IceInstX8632.h
@@ -142,10 +142,9 @@
 // Variable and SpillVariable share that slot.
 class SpillVariable : public Variable {
 public:
-  static SpillVariable *create(Cfg *Func, Type Ty, const CfgNode *Node,
-                               SizeT Index, const IceString &Name) {
-    return new (Func->allocate<SpillVariable>())
-        SpillVariable(Ty, Node, Index, Name);
+  static SpillVariable *create(Cfg *Func, Type Ty, SizeT Index,
+                               const IceString &Name) {
+    return new (Func->allocate<SpillVariable>()) SpillVariable(Ty, Index, Name);
   }
   const static OperandKind SpillVariableKind =
       static_cast<OperandKind>(kVariable_Target);
@@ -156,9 +155,8 @@
   Variable *getLinkedTo() const { return LinkedTo; }
   // Inherit dump() and emit() from Variable.
 private:
-  SpillVariable(Type Ty, const CfgNode *Node, SizeT Index,
-                const IceString &Name)
-      : Variable(SpillVariableKind, Ty, Node, Index, Name), LinkedTo(NULL) {}
+  SpillVariable(Type Ty, SizeT Index, const IceString &Name)
+      : Variable(SpillVariableKind, Ty, Index, Name), LinkedTo(NULL) {}
   Variable *LinkedTo;
 };
 
@@ -393,16 +391,16 @@
 // updates the stack offset during code emission.
 class InstX8632AdjustStack : public InstX8632 {
 public:
-  static InstX8632AdjustStack *create(Cfg *Func, SizeT Amount) {
+  static InstX8632AdjustStack *create(Cfg *Func, SizeT Amount, Variable *Esp) {
     return new (Func->allocate<InstX8632AdjustStack>())
-        InstX8632AdjustStack(Func, Amount);
+        InstX8632AdjustStack(Func, Amount, Esp);
   }
   virtual void emit(const Cfg *Func) const;
   virtual void dump(const Cfg *Func) const;
   static bool classof(const Inst *Inst) { return isClassof(Inst, Adjuststack); }
 
 private:
-  InstX8632AdjustStack(Cfg *Func, SizeT Amount);
+  InstX8632AdjustStack(Cfg *Func, SizeT Amount, Variable *Esp);
   InstX8632AdjustStack(const InstX8632AdjustStack &) LLVM_DELETED_FUNCTION;
   InstX8632AdjustStack &operator=(const InstX8632AdjustStack &)
       LLVM_DELETED_FUNCTION;
diff --git a/src/IceLiveness.cpp b/src/IceLiveness.cpp
index 47ef358..e2703c2 100644
--- a/src/IceLiveness.cpp
+++ b/src/IceLiveness.cpp
@@ -41,10 +41,10 @@
   // block.
   for (SizeT i = 0; i < NumVars; ++i) {
     Variable *Var = Func->getVariables()[i];
-    if (Var->isMultiblockLife()) {
+    if (Func->getVMetadata()->isMultiBlock(Var)) {
       ++NumGlobals;
     } else {
-      SizeT Index = Var->getLocalUseNode()->getIndex();
+      SizeT Index = Func->getVMetadata()->getLocalUseNode(Var)->getIndex();
       ++Nodes[Index].NumLocals;
     }
   }
@@ -64,11 +64,11 @@
     Variable *Var = Func->getVariables()[i];
     SizeT VarIndex = Var->getIndex();
     SizeT LiveIndex;
-    if (Var->isMultiblockLife()) {
+    if (Func->getVMetadata()->isMultiBlock(Var)) {
       LiveIndex = TmpNumGlobals++;
       LiveToVarMap[LiveIndex] = Var;
     } else {
-      SizeT NodeIndex = Var->getLocalUseNode()->getIndex();
+      SizeT NodeIndex = Func->getVMetadata()->getLocalUseNode(Var)->getIndex();
       LiveIndex = Nodes[NodeIndex].NumLocals++;
       Nodes[NodeIndex].LiveToVarMap[LiveIndex] = Var;
       LiveIndex += NumGlobals;
diff --git a/src/IceOperand.cpp b/src/IceOperand.cpp
index e4aaf24..9e523be 100644
--- a/src/IceOperand.cpp
+++ b/src/IceOperand.cpp
@@ -13,6 +13,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "IceCfg.h"
+#include "IceCfgNode.h"
 #include "IceInst.h"
 #include "IceOperand.h"
 #include "IceTargetLowering.h" // dumping stack/frame pointer register
@@ -138,48 +139,6 @@
   return false;
 }
 
-void Variable::setUse(const Inst *Inst, const CfgNode *Node) {
-  if (DefNode == NULL)
-    return;
-  if (llvm::isa<InstPhi>(Inst) || Node != DefNode)
-    DefNode = NULL;
-}
-
-void Variable::setDefinition(Inst *Inst, const CfgNode *Node) {
-  if (DefInst && !DefInst->isDeleted() && DefInst != Inst) {
-    // Detect when a variable is being defined multiple times,
-    // particularly for Phi instruction lowering.  If this happens, we
-    // need to lock DefInst to NULL.
-    DefInst = NULL;
-    DefNode = NULL;
-    return;
-  }
-  if (DefNode == NULL)
-    return;
-  DefInst = Inst;
-  if (Node != DefNode)
-    DefNode = NULL;
-}
-
-void Variable::replaceDefinition(Inst *Inst, const CfgNode *Node) {
-  DefInst = NULL;
-  setDefinition(Inst, Node);
-}
-
-void Variable::setIsArg(Cfg *Func, bool IsArg) {
-  if (IsArg) {
-    IsArgument = true;
-    if (DefNode == NULL)
-      return;
-    CfgNode *Entry = Func->getEntryNode();
-    if (DefNode == Entry)
-      return;
-    DefNode = NULL;
-  } else {
-    IsArgument = false;
-  }
-}
-
 IceString Variable::getName() const {
   if (!Name.empty())
     return Name;
@@ -191,16 +150,156 @@
 Variable Variable::asType(Type Ty) {
   // Note: This returns a Variable, even if the "this" object is a
   // subclass of Variable.
-  Variable V(kVariable, Ty, DefNode, Number, Name);
+  Variable V(kVariable, Ty, Number, Name);
   V.RegNum = RegNum;
   V.StackOffset = StackOffset;
   return V;
 }
 
+void VariableTracking::markUse(const Inst *Instr, const CfgNode *Node,
+                               bool IsFromDef, bool IsImplicit) {
+  // TODO(stichnot): If the use occurs as a source operand in the
+  // first instruction of the block, and its definition is in this
+  // block's only predecessor, we might consider not marking this as a
+  // separate use.  This may also apply if it's the first instruction
+  // of the block that actually uses a Variable.
+  assert(Node);
+  bool MakeMulti = false;
+  // A phi source variable conservatively needs to be marked as
+  // multi-block, even if its definition is in the same block.  This
+  // is because there can be additional control flow before branching
+  // back to this node, and the variable is live throughout those
+  // nodes.
+  if (IsImplicit)
+    MakeMulti = true;
+  if (!IsFromDef && Instr && llvm::isa<InstPhi>(Instr))
+    MakeMulti = true;
+
+  if (!MakeMulti) {
+    switch (MultiBlock) {
+    case MBS_Unknown:
+      MultiBlock = MBS_SingleBlock;
+      SingleUseNode = Node;
+      break;
+    case MBS_SingleBlock:
+      if (SingleUseNode != Node)
+        MakeMulti = true;
+      break;
+    case MBS_MultiBlock:
+      break;
+    }
+  }
+
+  if (MakeMulti) {
+    MultiBlock = MBS_MultiBlock;
+    SingleUseNode = NULL;
+  }
+}
+
+void VariableTracking::markDef(const Inst *Instr, const CfgNode *Node) {
+  // TODO(stichnot): If the definition occurs in the last instruction
+  // of the block, consider not marking this as a separate use.  But
+  // be careful not to omit all uses of the variable if markDef() and
+  // markUse() both use this optimization.
+  const bool IsFromDef = true;
+  const bool IsImplicit = false;
+  markUse(Instr, Node, IsFromDef, IsImplicit);
+  switch (MultiDef) {
+  case MDS_Unknown:
+    MultiDef = MDS_SingleDef;
+    SingleDefInst = Instr;
+    break;
+  case MDS_SingleDef:
+    MultiDef = MDS_MultiDef;
+    SingleDefInst = NULL;
+    break;
+  case MDS_MultiDef:
+    break;
+  }
+}
+
+void VariablesMetadata::init() {
+  Metadata.clear();
+  Metadata.resize(Func->getNumVariables());
+
+  // Mark implicit args as being used in the entry node.
+  const VarList &ImplicitArgList = Func->getImplicitArgs();
+  for (VarList::const_iterator I = ImplicitArgList.begin(),
+                               E = ImplicitArgList.end();
+       I != E; ++I) {
+    const Variable *Var = *I;
+    const Inst *NoInst = NULL;
+    const CfgNode *EntryNode = Func->getEntryNode();
+    const bool IsFromDef = false;
+    const bool IsImplicit = true;
+    Metadata[Var->getIndex()].markUse(NoInst, EntryNode, IsFromDef, IsImplicit);
+  }
+
+  SizeT NumNodes = Func->getNumNodes();
+  for (SizeT N = 0; N < NumNodes; ++N) {
+    CfgNode *Node = Func->getNodes()[N];
+    const InstList &Insts = Node->getInsts();
+    for (InstList::const_iterator I = Insts.begin(), E = Insts.end(); I != E;
+         ++I) {
+      if ((*I)->isDeleted())
+        continue;
+      if (Variable *Dest = (*I)->getDest()) {
+        SizeT DestNum = Dest->getIndex();
+        assert(DestNum < Metadata.size());
+        Metadata[DestNum].markDef(*I, Node);
+      }
+      for (SizeT SrcNum = 0; SrcNum < (*I)->getSrcSize(); ++SrcNum) {
+        Operand *Src = (*I)->getSrc(SrcNum);
+        SizeT NumVars = Src->getNumVars();
+        for (SizeT J = 0; J < NumVars; ++J) {
+          const Variable *Var = Src->getVar(J);
+          SizeT VarNum = Var->getIndex();
+          assert(VarNum < Metadata.size());
+          const bool IsFromDef = false;
+          const bool IsImplicit = false;
+          Metadata[VarNum].markUse(*I, Node, IsFromDef, IsImplicit);
+        }
+      }
+    }
+  }
+}
+
+bool VariablesMetadata::isMultiDef(const Variable *Var) const {
+  if (Var->getIsArg())
+    return false;
+  if (!isTracked(Var))
+    return true; // conservative answer
+  SizeT VarNum = Var->getIndex();
+  // Conservatively return true if the state is unknown.
+  return Metadata[VarNum].getMultiDef() != VariableTracking::MDS_SingleDef;
+}
+
+bool VariablesMetadata::isMultiBlock(const Variable *Var) const {
+  if (getDefinition(Var) == NULL)
+    return true;
+  SizeT VarNum = Var->getIndex();
+  // Conservatively return true if the state is unknown.
+  return Metadata[VarNum].getMultiBlock() != VariableTracking::MBS_SingleBlock;
+}
+
+const Inst *VariablesMetadata::getDefinition(const Variable *Var) const {
+  if (!isTracked(Var))
+    return NULL; // conservative answer
+  SizeT VarNum = Var->getIndex();
+  return Metadata[VarNum].getDefinition();
+}
+
+const CfgNode *VariablesMetadata::getLocalUseNode(const Variable *Var) const {
+  if (!isTracked(Var))
+    return NULL; // conservative answer
+  SizeT VarNum = Var->getIndex();
+  return Metadata[VarNum].getNode();
+}
+
 // ======================== dump routines ======================== //
 
 void Variable::emit(const Cfg *Func) const {
-  Func->getTarget()->emitVariable(this, Func);
+  Func->getTarget()->emitVariable(this);
 }
 
 void Variable::dump(const Cfg *Func, Ostream &Str) const {
@@ -208,9 +307,6 @@
     Str << "%" << getName();
     return;
   }
-  const CfgNode *CurrentNode = Func->getCurrentNode();
-  (void)CurrentNode; // used only in assert()
-  assert(CurrentNode == NULL || DefNode == NULL || DefNode == CurrentNode);
   if (Func->getContext()->isVerbose(IceV_RegOrigins) ||
       (!hasReg() && !Func->getTarget()->hasComputedFrame()))
     Str << "%" << getName();
diff --git a/src/IceOperand.h b/src/IceOperand.h
index 7fedfd2..727ea3d 100644
--- a/src/IceOperand.h
+++ b/src/IceOperand.h
@@ -347,10 +347,10 @@
   Variable &operator=(const Variable &) LLVM_DELETED_FUNCTION;
 
 public:
-  static Variable *create(Cfg *Func, Type Ty, const CfgNode *Node, SizeT Index,
+  static Variable *create(Cfg *Func, Type Ty, SizeT Index,
                           const IceString &Name) {
     return new (Func->allocate<Variable>())
-        Variable(kVariable, Ty, Node, Index, Name);
+        Variable(kVariable, Ty, Index, Name);
   }
 
   SizeT getIndex() const { return Number; }
@@ -361,24 +361,10 @@
     Name = NewName;
   }
 
-  Inst *getDefinition() const { return DefInst; }
-  void setDefinition(Inst *Inst, const CfgNode *Node);
-  void replaceDefinition(Inst *Inst, const CfgNode *Node);
-
-  const CfgNode *getLocalUseNode() const { return DefNode; }
-  bool isMultiblockLife() const { return (DefNode == NULL); }
-  void setUse(const Inst *Inst, const CfgNode *Node);
-
-  // Multidef means a variable is non-SSA and has multiple defining
-  // instructions.  Currently this classification is limited to SSA
-  // lowering temporaries where the definitions are in different basic
-  // blocks, and it is not maintained during target lowering when the
-  // same temporary may be updated in consecutive instructions.
-  bool getIsMultidef() const { return IsMultidef; }
-  void setIsMultidef() { IsMultidef = true; }
-
   bool getIsArg() const { return IsArgument; }
-  void setIsArg(Cfg *Func, bool IsArg = true);
+  void setIsArg(bool Val = true) { IsArgument = Val; }
+  bool getIsImplicitArg() const { return IsImplicitArgument; }
+  void setIsImplicitArg(bool Val = true) { IsImplicitArgument = Val; }
 
   int32_t getStackOffset() const { return StackOffset; }
   void setStackOffset(int32_t Offset) { StackOffset = Offset; }
@@ -447,13 +433,11 @@
   virtual ~Variable() {}
 
 protected:
-  Variable(OperandKind K, Type Ty, const CfgNode *Node, SizeT Index,
-           const IceString &Name)
-      : Operand(K, Ty), Number(Index), Name(Name), DefInst(NULL), DefNode(Node),
-        IsMultidef(false), IsArgument(false), StackOffset(0),
-        RegNum(NoRegister), RegNumTmp(NoRegister), Weight(1),
-        RegisterPreference(NULL), AllowRegisterOverlap(false), LoVar(NULL),
-        HiVar(NULL) {
+  Variable(OperandKind K, Type Ty, SizeT Index, const IceString &Name)
+      : Operand(K, Ty), Number(Index), Name(Name), IsArgument(false),
+        IsImplicitArgument(false), StackOffset(0), RegNum(NoRegister),
+        RegNumTmp(NoRegister), Weight(1), RegisterPreference(NULL),
+        AllowRegisterOverlap(false), LoVar(NULL), HiVar(NULL) {
     Vars = VarsReal;
     Vars[0] = this;
     NumVars = 1;
@@ -463,18 +447,8 @@
   const SizeT Number;
   // Name is optional.
   IceString Name;
-  // DefInst is the instruction that produces this variable as its
-  // dest.
-  Inst *DefInst;
-  // DefNode is the node where this variable was produced, and is
-  // reset to NULL if it is used outside that node.  This is used for
-  // detecting isMultiblockLife().  TODO: Collapse this to a single
-  // bit and use a separate pass to calculate the values across the
-  // Cfg.  This saves space in the Variable, and removes the fragility
-  // of incrementally computing and maintaining the information.
-  const CfgNode *DefNode;
-  bool IsMultidef;
   bool IsArgument;
+  bool IsImplicitArgument;
   // StackOffset is the canonical location on stack (only if
   // RegNum<0 || IsArgument).
   int32_t StackOffset;
@@ -509,6 +483,60 @@
   Variable *VarsReal[1];
 };
 
+// VariableTracking tracks the metadata for a single variable.
+class VariableTracking {
+public:
+  enum MultiDefState {
+    // TODO(stichnot): Consider using just a simple counter.
+    MDS_Unknown,
+    MDS_SingleDef,
+    MDS_MultiDef
+  };
+  enum MultiBlockState {
+    MBS_Unknown,
+    MBS_SingleBlock,
+    MBS_MultiBlock
+  };
+  VariableTracking()
+      : MultiDef(MDS_Unknown), MultiBlock(MBS_Unknown), SingleUseNode(NULL),
+        SingleDefInst(NULL) {}
+  MultiDefState getMultiDef() const { return MultiDef; }
+  MultiBlockState getMultiBlock() const { return MultiBlock; }
+  const Inst *getDefinition() const { return SingleDefInst; }
+  const CfgNode *getNode() const { return SingleUseNode; }
+  void markUse(const Inst *Instr, const CfgNode *Node, bool IsFromDef,
+               bool IsImplicit);
+  void markDef(const Inst *Instr, const CfgNode *Node);
+
+private:
+  VariableTracking &operator=(const VariableTracking &) LLVM_DELETED_FUNCTION;
+  MultiDefState MultiDef;
+  MultiBlockState MultiBlock;
+  const CfgNode *SingleUseNode;
+  const Inst *SingleDefInst;
+};
+
+// VariablesMetadata analyzes and summarizes the metadata for the
+// complete set of Variables.
+class VariablesMetadata {
+public:
+  VariablesMetadata(const Cfg *Func) : Func(Func) {}
+  void init();
+  bool isTracked(const Variable *Var) const {
+    return Var->getIndex() < Metadata.size();
+  }
+  bool isMultiDef(const Variable *Var) const;
+  const Inst *getDefinition(const Variable *Var) const;
+  bool isMultiBlock(const Variable *Var) const;
+  const CfgNode *getLocalUseNode(const Variable *Var) const;
+
+private:
+  const Cfg *Func;
+  std::vector<VariableTracking> Metadata;
+  VariablesMetadata(const VariablesMetadata &) LLVM_DELETED_FUNCTION;
+  VariablesMetadata &operator=(const VariablesMetadata &) LLVM_DELETED_FUNCTION;
+};
+
 } // end of namespace Ice
 
 #endif // SUBZERO_SRC_ICEOPERAND_H
diff --git a/src/IceTargetLowering.cpp b/src/IceTargetLowering.cpp
index 4ab6c63..3bae591 100644
--- a/src/IceTargetLowering.cpp
+++ b/src/IceTargetLowering.cpp
@@ -53,7 +53,6 @@
 
 void LoweringContext::insert(Inst *Inst) {
   getNode()->getInsts().insert(Next, Inst);
-  Inst->updateVars(getNode());
 }
 
 void LoweringContext::skipDeleted(InstList::iterator &I) const {
diff --git a/src/IceTargetLowering.h b/src/IceTargetLowering.h
index 7383fff..99716be 100644
--- a/src/IceTargetLowering.h
+++ b/src/IceTargetLowering.h
@@ -172,7 +172,7 @@
   virtual const llvm::SmallBitVector &getRegisterSetForType(Type Ty) const = 0;
   void regAlloc();
 
-  virtual void emitVariable(const Variable *Var, const Cfg *Func) const = 0;
+  virtual void emitVariable(const Variable *Var) const = 0;
 
   // Performs target-specific argument lowering.
   virtual void lowerArguments() = 0;
diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp
index f66a364..33a5741 100644
--- a/src/IceTargetLoweringX8632.cpp
+++ b/src/IceTargetLoweringX8632.cpp
@@ -322,6 +322,7 @@
 
   // Address mode optimization.
   Timer T_doAddressOpt;
+  Func->getVMetadata()->init();
   Func->doAddressOpt();
   T_doAddressOpt.printElapsedUs(Context, "doAddressOpt()");
 
@@ -470,10 +471,13 @@
   assert(RegNum < PhysicalRegisters.size());
   Variable *Reg = PhysicalRegisters[RegNum];
   if (Reg == NULL) {
-    CfgNode *Node = NULL; // NULL means multi-block lifetime
-    Reg = Func->makeVariable(IceType_i32, Node);
+    Reg = Func->makeVariable(IceType_i32);
     Reg->setRegNum(RegNum);
     PhysicalRegisters[RegNum] = Reg;
+    // Specially mark esp as an "argument" so that it is considered
+    // live upon function entry.
+    if (RegNum == RegX8632::Reg_esp)
+      Func->addImplicitArg(Reg);
   }
   return Reg;
 }
@@ -505,10 +509,8 @@
   }
 }
 
-void TargetX8632::emitVariable(const Variable *Var, const Cfg *Func) const {
+void TargetX8632::emitVariable(const Variable *Var) const {
   Ostream &Str = Ctx->getStrEmit();
-  assert(Var->getLocalUseNode() == NULL ||
-         Var->getLocalUseNode() == Func->getCurrentNode());
   if (Var->hasReg()) {
     Str << getRegName(Var->getRegNum(), Var->getType());
     return;
@@ -548,11 +550,10 @@
     int32_t RegNum = RegX8632::Reg_xmm0 + NumXmmArgs;
     ++NumXmmArgs;
     IceString Name = "home_reg:" + Arg->getName();
-    const CfgNode *DefNode = NULL;
-    Variable *RegisterArg = Func->makeVariable(Ty, DefNode, Name);
+    Variable *RegisterArg = Func->makeVariable(Ty, Name);
     RegisterArg->setRegNum(RegNum);
-    RegisterArg->setIsArg(Func);
-    Arg->setIsArg(Func, false);
+    RegisterArg->setIsArg();
+    Arg->setIsArg(false);
 
     Args[I] = RegisterArg;
     Context.insert(InstAssign::create(Func, Arg, RegisterArg));
@@ -675,6 +676,7 @@
   size_t InArgsSizeBytes = 0;
   size_t PreservedRegsSizeBytes = 0;
   SpillAreaSizeBytes = 0;
+  const VariablesMetadata *VMetadata = Func->getVMetadata();
   Context.init(Node);
   Context.setInsertPoint(Context.getCur());
 
@@ -743,11 +745,11 @@
     size_t Increment = typeWidthInBytesOnStack(Var->getType());
     if (!SpillAreaAlignmentBytes)
       SpillAreaAlignmentBytes = Increment;
-    if (SimpleCoalescing) {
-      if (Var->isMultiblockLife()) {
+    if (SimpleCoalescing && VMetadata->isTracked(Var)) {
+      if (VMetadata->isMultiBlock(Var)) {
         GlobalsSize += Increment;
       } else {
-        SizeT NodeIndex = Var->getLocalUseNode()->getIndex();
+        SizeT NodeIndex = VMetadata->getLocalUseNode(Var)->getIndex();
         LocalsSize[NodeIndex] += Increment;
         if (LocalsSize[NodeIndex] > SpillAreaSizeBytes)
           SpillAreaSizeBytes = LocalsSize[NodeIndex];
@@ -852,12 +854,12 @@
        I != E; ++I) {
     Variable *Var = *I;
     size_t Increment = typeWidthInBytesOnStack(Var->getType());
-    if (SimpleCoalescing) {
-      if (Var->isMultiblockLife()) {
+    if (SimpleCoalescing && VMetadata->isTracked(Var)) {
+      if (VMetadata->isMultiBlock(Var)) {
         GlobalsSpaceUsed += Increment;
         NextStackOffset = GlobalsSpaceUsed;
       } else {
-        SizeT NodeIndex = Var->getLocalUseNode()->getIndex();
+        SizeT NodeIndex = VMetadata->getLocalUseNode(Var)->getIndex();
         LocalsSize[NodeIndex] += Increment;
         NextStackOffset = SpillAreaPaddingBytes +
                           GlobalsAndSubsequentPaddingSize +
@@ -1035,14 +1037,12 @@
     return;
   }
   assert(Hi == NULL);
-  Lo = Func->makeVariable(IceType_i32, Context.getNode(),
-                          Var->getName() + "__lo");
-  Hi = Func->makeVariable(IceType_i32, Context.getNode(),
-                          Var->getName() + "__hi");
+  Lo = Func->makeVariable(IceType_i32, Var->getName() + "__lo");
+  Hi = Func->makeVariable(IceType_i32, Var->getName() + "__hi");
   Var->setLoHi(Lo, Hi);
   if (Var->getIsArg()) {
-    Lo->setIsArg(Func);
-    Hi->setIsArg(Func);
+    Lo->setIsArg();
+    Hi->setIsArg();
   }
 }
 
@@ -2276,8 +2276,7 @@
       Variable *T = NULL;
       // TODO: Should be able to force a spill setup by calling legalize() with
       // Legal_Mem and not Legal_Reg or Legal_Imm.
-      SpillVariable *SpillVar =
-          Func->makeVariable<SpillVariable>(SrcType, Context.getNode());
+      SpillVariable *SpillVar = Func->makeVariable<SpillVariable>(SrcType);
       SpillVar->setLinkedTo(Dest);
       Variable *Spill = SpillVar;
       Spill->setWeight(RegWeight::Zero);
@@ -2294,8 +2293,7 @@
       //   a_lo.i32 = t_lo.i32
       //   t_hi.i32 = hi(s.f64)
       //   a_hi.i32 = t_hi.i32
-      SpillVariable *SpillVar =
-          Func->makeVariable<SpillVariable>(IceType_f64, Context.getNode());
+      SpillVariable *SpillVar = Func->makeVariable<SpillVariable>(IceType_f64);
       SpillVar->setLinkedTo(llvm::dyn_cast<Variable>(Src0RM));
       Variable *Spill = SpillVar;
       Spill->setWeight(RegWeight::Zero);
@@ -2325,8 +2323,7 @@
       //   t_hi.i32 = b_hi.i32
       //   hi(s.f64) = t_hi.i32
       //   a.f64 = s.f64
-      SpillVariable *SpillVar =
-          Func->makeVariable<SpillVariable>(IceType_f64, Context.getNode());
+      SpillVariable *SpillVar = Func->makeVariable<SpillVariable>(IceType_f64);
       SpillVar->setLinkedTo(Dest);
       Variable *Spill = SpillVar;
       Spill->setWeight(RegWeight::Zero);
@@ -2349,8 +2346,7 @@
     case IceType_v8i1: {
       assert(Src0->getType() == IceType_i8);
       InstCall *Call = makeHelperCall("Sz_bitcast_i8_to_v8i1", Dest, 1);
-      Variable *Src0AsI32 = Func->makeVariable(stackSlotType(),
-                                               Context.getNode());
+      Variable *Src0AsI32 = Func->makeVariable(stackSlotType());
       // Arguments to functions are required to be at least 32 bits wide.
       lowerCast(InstCast::create(Func, InstCast::Zext, Src0AsI32, Src0));
       Call->addArg(Src0AsI32);
@@ -2359,8 +2355,7 @@
     case IceType_v16i1: {
       assert(Src0->getType() == IceType_i16);
       InstCall *Call = makeHelperCall("Sz_bitcast_i16_to_v16i1", Dest, 1);
-      Variable *Src0AsI32 = Func->makeVariable(stackSlotType(),
-                                               Context.getNode());
+      Variable *Src0AsI32 = Func->makeVariable(stackSlotType());
       // Arguments to functions are required to be at least 32 bits wide.
       lowerCast(InstCast::create(Func, InstCast::Zext, Src0AsI32, Src0));
       Call->addArg(Src0AsI32);
@@ -2429,7 +2424,7 @@
     //
     // TODO(wala): use legalize(SourceVectNotLegalized, Legal_Mem) when
     // support for legalizing to mem is implemented.
-    Variable *Slot = Func->makeVariable(Ty, Context.getNode());
+    Variable *Slot = Func->makeVariable(Ty);
     Slot->setWeight(RegWeight::Zero);
     _movp(Slot, legalizeToVar(SourceVectNotLegalized));
 
@@ -2584,8 +2579,8 @@
         NewTy = IceType_v16i8;
         break;
       }
-      Variable *NewSrc0 = Func->makeVariable(NewTy, Context.getNode());
-      Variable *NewSrc1 = Func->makeVariable(NewTy, Context.getNode());
+      Variable *NewSrc0 = Func->makeVariable(NewTy);
+      Variable *NewSrc1 = Func->makeVariable(NewTy);
       lowerCast(InstCast::create(Func, InstCast::Sext, NewSrc0, Src0));
       lowerCast(InstCast::create(Func, InstCast::Sext, NewSrc1, Src1));
       Src0 = NewSrc0;
@@ -2760,8 +2755,7 @@
   if (ElementTy == IceType_i1) {
     // Expand the element to the appropriate size for it to be inserted
     // in the vector.
-    Variable *Expanded =
-        Func->makeVariable(InVectorElementTy, Context.getNode());
+    Variable *Expanded = Func->makeVariable(InVectorElementTy);
     InstCast *Cast = InstCast::create(Func, InstCast::Zext, Expanded,
                                       ElementToInsertNotLegalized);
     lowerCast(Cast);
@@ -2853,7 +2847,7 @@
     //
     // TODO(wala): use legalize(SourceVectNotLegalized, Legal_Mem) when
     // support for legalizing to mem is implemented.
-    Variable *Slot = Func->makeVariable(Ty, Context.getNode());
+    Variable *Slot = Func->makeVariable(Ty);
     Slot->setWeight(RegWeight::Zero);
     _movp(Slot, legalizeToVar(SourceVectNotLegalized));
 
@@ -3123,7 +3117,7 @@
     // wide.
     Operand *ValOp = Instr->getArg(1);
     assert(ValOp->getType() == IceType_i8);
-    Variable *ValExt = Func->makeVariable(stackSlotType(), Context.getNode());
+    Variable *ValExt = Func->makeVariable(stackSlotType());
     lowerCast(InstCast::create(Func, InstCast::Zext, ValExt, ValOp));
     InstCall *Call = makeHelperCall("memset", NULL, 3);
     Call->addArg(Instr->getArg(0));
@@ -3579,17 +3573,18 @@
   Str << ", Shift=" << Shift << ", Offset=" << Offset << "\n";
 }
 
-bool matchTransitiveAssign(Variable *&Var, const Inst *&Reason) {
+bool matchTransitiveAssign(const VariablesMetadata *VMetadata, Variable *&Var,
+                           const Inst *&Reason) {
   // Var originates from Var=SrcVar ==>
   //   set Var:=SrcVar
   if (Var == NULL)
     return false;
-  if (const Inst *VarAssign = Var->getDefinition()) {
+  if (const Inst *VarAssign = VMetadata->getDefinition(Var)) {
     if (llvm::isa<InstAssign>(VarAssign)) {
       Operand *SrcOp = VarAssign->getSrc(0);
       assert(SrcOp);
       if (Variable *SrcVar = llvm::dyn_cast<Variable>(SrcOp)) {
-        if (!SrcVar->getIsMultidef() &&
+        if (!VMetadata->isMultiDef(SrcVar) &&
             // TODO: ensure SrcVar stays single-BB
             true) {
           Var = SrcVar;
@@ -3602,7 +3597,8 @@
   return false;
 }
 
-bool matchCombinedBaseIndex(Variable *&Base, Variable *&Index, uint16_t &Shift,
+bool matchCombinedBaseIndex(const VariablesMetadata *VMetadata, Variable *&Base,
+                            Variable *&Index, uint16_t &Shift,
                             const Inst *&Reason) {
   // Index==NULL && Base is Base=Var1+Var2 ==>
   //   set Base=Var1, Index=Var2, Shift=0
@@ -3610,16 +3606,16 @@
     return false;
   if (Index != NULL)
     return false;
-  const Inst *BaseInst = Base->getDefinition();
+  const Inst *BaseInst = VMetadata->getDefinition(Base);
   if (BaseInst == NULL)
     return false;
   if (BaseInst->getSrcSize() < 2)
     return false;
   if (Variable *Var1 = llvm::dyn_cast<Variable>(BaseInst->getSrc(0))) {
-    if (Var1->getIsMultidef())
+    if (VMetadata->isMultiDef(Var1))
       return false;
     if (Variable *Var2 = llvm::dyn_cast<Variable>(BaseInst->getSrc(1))) {
-      if (Var2->getIsMultidef())
+      if (VMetadata->isMultiDef(Var2))
         return false;
       if (isAdd(BaseInst) &&
           // TODO: ensure Var1 and Var2 stay single-BB
@@ -3635,12 +3631,13 @@
   return false;
 }
 
-bool matchShiftedIndex(Variable *&Index, uint16_t &Shift, const Inst *&Reason) {
+bool matchShiftedIndex(const VariablesMetadata *VMetadata, Variable *&Index,
+                       uint16_t &Shift, const Inst *&Reason) {
   // Index is Index=Var*Const && log2(Const)+Shift<=3 ==>
   //   Index=Var, Shift+=log2(Const)
   if (Index == NULL)
     return false;
-  const Inst *IndexInst = Index->getDefinition();
+  const Inst *IndexInst = VMetadata->getDefinition(Index);
   if (IndexInst == NULL)
     return false;
   if (IndexInst->getSrcSize() < 2)
@@ -3651,7 +3648,7 @@
       if (ConstantInteger32 *Const =
               llvm::dyn_cast<ConstantInteger32>(ArithInst->getSrc(1))) {
         if (ArithInst->getOp() == InstArithmetic::Mul &&
-            !Var->getIsMultidef() && Const->getType() == IceType_i32) {
+            !VMetadata->isMultiDef(Var) && Const->getType() == IceType_i32) {
           uint64_t Mult = Const->getValue();
           uint32_t LogMult;
           switch (Mult) {
@@ -3683,14 +3680,15 @@
   return false;
 }
 
-bool matchOffsetBase(Variable *&Base, int32_t &Offset, const Inst *&Reason) {
+bool matchOffsetBase(const VariablesMetadata *VMetadata, Variable *&Base,
+                     int32_t &Offset, const Inst *&Reason) {
   // Base is Base=Var+Const || Base is Base=Const+Var ==>
   //   set Base=Var, Offset+=Const
   // Base is Base=Var-Const ==>
   //   set Base=Var, Offset-=Const
   if (Base == NULL)
     return false;
-  const Inst *BaseInst = Base->getDefinition();
+  const Inst *BaseInst = VMetadata->getDefinition(Base);
   if (BaseInst == NULL)
     return false;
   if (const InstArithmetic *ArithInst =
@@ -3709,7 +3707,7 @@
       Const = llvm::dyn_cast<ConstantInteger32>(ArithInst->getSrc(0));
       Var = llvm::dyn_cast<Variable>(ArithInst->getSrc(1));
     }
-    if (Var == NULL || Const == NULL || Var->getIsMultidef())
+    if (Var == NULL || Const == NULL || VMetadata->isMultiDef(Var))
       return false;
     int32_t MoreOffset = IsAdd ? Const->getValue() : -Const->getValue();
     if (WouldOverflowAdd(Offset, MoreOffset))
@@ -3737,17 +3735,18 @@
   // blocks, then don't go further.  Alternatively (?), never consider
   // a transformation that would change a variable that is currently
   // *not* live across basic block boundaries into one that *is*.
-  if (Base->isMultiblockLife() /* || Base->getUseCount() > 1*/)
+  if (Func->getVMetadata()->isMultiBlock(Base) /* || Base->getUseCount() > 1*/)
     return;
 
+  const VariablesMetadata *VMetadata = Func->getVMetadata();
   bool Continue = true;
   while (Continue) {
     const Inst *Reason = NULL;
-    if (matchTransitiveAssign(Base, Reason) ||
-        matchTransitiveAssign(Index, Reason) ||
-        matchCombinedBaseIndex(Base, Index, Shift, Reason) ||
-        matchShiftedIndex(Index, Shift, Reason) ||
-        matchOffsetBase(Base, Offset, Reason)) {
+    if (matchTransitiveAssign(VMetadata, Base, Reason) ||
+        matchTransitiveAssign(VMetadata, Index, Reason) ||
+        matchCombinedBaseIndex(VMetadata, Base, Index, Shift, Reason) ||
+        matchShiftedIndex(VMetadata, Index, Shift, Reason) ||
+        matchOffsetBase(VMetadata, Base, Offset, Reason)) {
       dumpAddressOpt(Func, Base, Index, Shift, Offset, Reason);
     } else {
       Continue = false;
@@ -3939,7 +3938,7 @@
     // Sign extend the condition operand if applicable.
     if (SrcTy == IceType_v4f32) {
       // The sext operation takes only integer arguments.
-      Variable *T3 = Func->makeVariable(IceType_v4i32, Context.getNode());
+      Variable *T3 = Func->makeVariable(IceType_v4i32);
       lowerCast(InstCast::create(Func, InstCast::Sext, T3, Condition));
       _movp(T, T3);
     } else if (typeElementType(SrcTy) != IceType_i1) {
@@ -4070,17 +4069,17 @@
     Constant *Index = Ctx->getConstantInt32(IceType_i32, I);
 
     // Extract the next two inputs.
-    Variable *Op0 = Func->makeVariable(ElementTy, Context.getNode());
+    Variable *Op0 = Func->makeVariable(ElementTy);
     lowerExtractElement(InstExtractElement::create(Func, Op0, Src0, Index));
-    Variable *Op1 = Func->makeVariable(ElementTy, Context.getNode());
+    Variable *Op1 = Func->makeVariable(ElementTy);
     lowerExtractElement(InstExtractElement::create(Func, Op1, Src1, Index));
 
     // Perform the arithmetic as a scalar operation.
-    Variable *Res = Func->makeVariable(ElementTy, Context.getNode());
+    Variable *Res = Func->makeVariable(ElementTy);
     lowerArithmetic(InstArithmetic::create(Func, Kind, Res, Op0, Op1));
 
     // Insert the result into position.
-    Variable *DestT = Func->makeVariable(Ty, Context.getNode());
+    Variable *DestT = Func->makeVariable(Ty);
     lowerInsertElement(InstInsertElement::create(Func, DestT, T, Res, Index));
     T = DestT;
     // TODO(stichnot): Use postLower() in -Om1 mode to avoid buildup of
@@ -4324,7 +4323,7 @@
 Variable *TargetX8632::makeReg(Type Type, int32_t RegNum) {
   // There aren't any 64-bit integer registers for x86-32.
   assert(Type != IceType_i64);
-  Variable *Reg = Func->makeVariable(Type, Context.getNode());
+  Variable *Reg = Func->makeVariable(Type);
   if (RegNum == Variable::NoRegister)
     Reg->setWeightInfinite();
   else
diff --git a/src/IceTargetLoweringX8632.h b/src/IceTargetLoweringX8632.h
index 1b65b3f..39609cf 100644
--- a/src/IceTargetLoweringX8632.h
+++ b/src/IceTargetLoweringX8632.h
@@ -52,7 +52,7 @@
     static const uint8_t Padding[] = { 0xF4 };
     return llvm::ArrayRef<uint8_t>(Padding, 1);
   }
-  virtual void emitVariable(const Variable *Var, const Cfg *Func) const;
+  virtual void emitVariable(const Variable *Var) const;
   virtual void lowerArguments();
   virtual void addProlog(CfgNode *Node);
   virtual void addEpilog(CfgNode *Node);
@@ -190,7 +190,8 @@
     Context.insert(InstX8632Add::create(Func, Dest, Src0));
   }
   void _adjust_stack(int32_t Amount) {
-    Context.insert(InstX8632AdjustStack::create(Func, Amount));
+    Context.insert(InstX8632AdjustStack::create(
+        Func, Amount, getPhysicalRegister(RegX8632::Reg_esp)));
   }
   void _addps(Variable *Dest, Operand *Src0) {
     Context.insert(InstX8632Addps::create(Func, Dest, Src0));
diff --git a/src/PNaClTranslator.cpp b/src/PNaClTranslator.cpp
index 5b7c0d2..35108cc 100644
--- a/src/PNaClTranslator.cpp
+++ b/src/PNaClTranslator.cpp
@@ -948,7 +948,7 @@
       // Recover since we can't throw an exception.
       Ty = Ice::IceType_i32;
     }
-    return Func->makeVariable(Ty, CurrentNode);
+    return Func->makeVariable(Ty);
   }
 
   // Generates the next available local variable using the given type.