Subzero: Speed up VariablesMetadata initialization.

Currently, O2 calls VariablesMetadata::init() 4 times:

- Twice for liveness analysis, where only multi-block use information is needed for dealing with sparse bit vectors.

- Once for address mode inference, where single-definition information is needed.

- Once for register allocation, where all information is needed, including the set of all definitions which is needed for determining AllowOverlap.

So we limit the amount of data we gather based on the actual need.

BUG= none
R=jvoung@chromium.org

Review URL: https://codereview.chromium.org/650613003
diff --git a/src/IceOperand.h b/src/IceOperand.h
index 3465ce5..6d31127 100644
--- a/src/IceOperand.h
+++ b/src/IceOperand.h
@@ -516,6 +516,11 @@
   Variable *VarsReal[1];
 };
 
+enum MetadataKind {
+  VMK_Uses,       // Track only uses, not defs
+  VMK_SingleDefs, // Track uses+defs, but only record single def
+  VMK_All         // Track uses+defs, including full def list
+};
 typedef std::vector<const Inst *> InstDefList;
 
 // VariableTracking tracks the metadata for a single variable.  It is
@@ -539,16 +544,17 @@
   };
   VariableTracking()
       : MultiDef(MDS_Unknown), MultiBlock(MBS_Unknown), SingleUseNode(NULL),
-        SingleDefNode(NULL) {}
+        SingleDefNode(NULL), FirstOrSingleDefinition(NULL) {}
   MultiDefState getMultiDef() const { return MultiDef; }
   MultiBlockState getMultiBlock() const { return MultiBlock; }
   const Inst *getFirstDefinition() const;
   const Inst *getSingleDefinition() const;
-  const InstDefList &getDefinitions() const { return Definitions; }
+  const InstDefList &getLatterDefinitions() const { return Definitions; }
   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);
+  void markUse(MetadataKind TrackingKind, const Inst *Instr,
+               const CfgNode *Node, bool IsFromDef, bool IsImplicit);
+  void markDef(MetadataKind TrackingKind, const Inst *Instr,
+               const CfgNode *Node);
 
 private:
   MultiDefState MultiDef;
@@ -557,7 +563,8 @@
   const CfgNode *SingleDefNode;
   // All definitions of the variable are collected here, in increasing
   // order of instruction number.
-  InstDefList Definitions;
+  InstDefList Definitions;             // Only used if Kind==VMK_All
+  const Inst *FirstOrSingleDefinition; // == Definitions[0] if Kind==VMK_All
 };
 
 // VariablesMetadata analyzes and summarizes the metadata for the
@@ -570,7 +577,7 @@
   VariablesMetadata(const Cfg *Func) : Func(Func) {}
   // Initialize the state by traversing all instructions/variables in
   // the CFG.
-  void init();
+  void init(MetadataKind TrackingKind);
   // Returns whether the given Variable is tracked in this object.  It
   // should only return false if changes were made to the CFG after
   // running init(), in which case the state is stale and the results
@@ -594,7 +601,7 @@
   const Inst *getSingleDefinition(const Variable *Var) const;
   // Returns the list of all definition instructions of the given
   // Variable.
-  const InstDefList &getDefinitions(const Variable *Var) const;
+  const InstDefList &getLatterDefinitions(const Variable *Var) const;
 
   // Returns whether the given Variable is live across multiple
   // blocks.  Mainly, this is used to partition Variables into
@@ -610,6 +617,7 @@
 
 private:
   const Cfg *Func;
+  MetadataKind Kind;
   std::vector<VariableTracking> Metadata;
   const static InstDefList NoDefinitions;
 };