[XRay] A tool for Comparing xray function call graphs

Summary:
This is a tool for comparing the function graphs produced by the
llvm-xray graph too. It takes the form of a new subcommand of the
llvm-xray tool 'graph-diff'.

This initial version of the patch is very rough, but it is close to
feature complete.

Depends on D29363

Reviewers: dblaikie, dberris

Reviewed By: dberris

Subscribers: mgorny, llvm-commits

Differential Revision: https://reviews.llvm.org/D29320

llvm-svn: 301160
diff --git a/llvm/tools/llvm-xray/xray-graph.h b/llvm/tools/llvm-xray/xray-graph.h
index 1c7a3c0..81c2e0e 100644
--- a/llvm/tools/llvm-xray/xray-graph.h
+++ b/llvm/tools/llvm-xray/xray-graph.h
@@ -41,17 +41,18 @@
 
   /// An inner struct for common timing statistics information
   struct TimeStat {
-    uint64_t Count = 0;
-    double Min = 0;
-    double Median = 0;
-    double Pct90 = 0;
-    double Pct99 = 0;
-    double Max = 0;
-    double Sum = 0;
-    std::string getAsString(StatType T) const;
-    double compare(StatType T, const TimeStat &Other) const;
+    int64_t Count;
+    double Min;
+    double Median;
+    double Pct90;
+    double Pct99;
+    double Max;
+    double Sum;
+
+    std::string getString(StatType T) const;
+    double getDouble(StatType T) const;
   };
-  typedef uint64_t TimestampT;
+  using TimestampT = uint64_t;
 
   /// An inner struct for storing edge attributes for our graph. Here the
   /// attributes are mainly function call statistics.
@@ -68,7 +69,7 @@
   /// FIXME: Store more attributes based on instrumentation map.
   struct FunctionStats {
     std::string SymbolName;
-    TimeStat S;
+    TimeStat S = {};
   };
 
   struct FunctionAttr {
@@ -76,10 +77,10 @@
     uint64_t TSC;
   };
 
-  typedef SmallVector<FunctionAttr, 4> FunctionStack;
+  using FunctionStack = SmallVector<FunctionAttr, 4>;
 
-  typedef DenseMap<llvm::sys::ProcessInfo::ProcessId, FunctionStack>
-      PerThreadFunctionStackMap;
+  using PerThreadFunctionStackMap =
+      DenseMap<llvm::sys::ProcessInfo::ProcessId, FunctionStack>;
 
   class GraphT : public Graph<FunctionStats, CallStats, int32_t> {
   public:
@@ -88,8 +89,8 @@
   };
 
   GraphT G;
-  typedef typename decltype(G)::VertexIdentifier VertexIdentifier;
-  typedef typename decltype(G)::EdgeIdentifier EdgeIdentifier;
+  using VertexIdentifier = typename decltype(G)::VertexIdentifier;
+  using EdgeIdentifier = decltype(G)::EdgeIdentifier;
 
   /// Use a Map to store the Function stack for each thread whilst building the
   /// graph.
@@ -98,7 +99,7 @@
   PerThreadFunctionStackMap PerThreadFunctionStack;
 
   /// Usefull object for getting human readable Symbol Names.
-  const FuncIdConversionHelper &FuncIdHelper;
+  FuncIdConversionHelper FuncIdHelper;
   bool DeduceSiblingCalls = false;
   TimestampT CurrentMaxTSC = 0;
 
@@ -143,22 +144,90 @@
     return PerThreadFunctionStack;
   }
 
+  class Factory {
+  public:
+    bool KeepGoing;
+    bool DeduceSiblingCalls;
+    std::string InstrMap;
+    Trace Trace;
+    Expected<GraphRenderer> getGraphRenderer();
+  };
+
   /// Output the Embedded graph in DOT format on \p OS, labeling the edges by
   /// \p T
-  void exportGraphAsDOT(raw_ostream &OS, const XRayFileHeader &H,
-                        StatType EdgeLabel = StatType::NONE,
+  void exportGraphAsDOT(raw_ostream &OS, StatType EdgeLabel = StatType::NONE,
                         StatType EdgeColor = StatType::NONE,
                         StatType VertexLabel = StatType::NONE,
                         StatType VertexColor = StatType::NONE);
 
   /// Get a reference to the internal graph.
-  const GraphT &getGraph() {
-    calculateEdgeStatistics();
-    calculateVertexStatistics();
-    return G;
-  }
+  const GraphT &getGraph() { return G; }
 };
+
+/// Vector Sum of TimeStats
+inline GraphRenderer::TimeStat operator+(const GraphRenderer::TimeStat &A,
+                                         const GraphRenderer::TimeStat &B) {
+  return {A.Count + B.Count, A.Min + B.Min,     A.Median + B.Median,
+          A.Pct90 + B.Pct90, A.Pct99 + B.Pct99, A.Max + B.Max,
+          A.Sum + B.Sum};
 }
+
+/// Vector Difference of Timestats
+inline GraphRenderer::TimeStat operator-(const GraphRenderer::TimeStat &A,
+                                         const GraphRenderer::TimeStat &B) {
+
+  return {A.Count - B.Count, A.Min - B.Min,     A.Median - B.Median,
+          A.Pct90 - B.Pct90, A.Pct99 - B.Pct99, A.Max - B.Max,
+          A.Sum - B.Sum};
 }
 
+/// Scalar Diference of TimeStat and double
+inline GraphRenderer::TimeStat operator/(const GraphRenderer::TimeStat &A,
+                                         double B) {
+
+  return {static_cast<int64_t>(A.Count / B),
+          A.Min / B,
+          A.Median / B,
+          A.Pct90 / B,
+          A.Pct99 / B,
+          A.Max / B,
+          A.Sum / B};
+}
+
+/// Scalar product of TimeStat and Double
+inline GraphRenderer::TimeStat operator*(const GraphRenderer::TimeStat &A,
+                                         double B) {
+  return {static_cast<int64_t>(A.Count * B),
+          A.Min * B,
+          A.Median * B,
+          A.Pct90 * B,
+          A.Pct99 * B,
+          A.Max * B,
+          A.Sum * B};
+}
+
+/// Scalar product of double TimeStat
+inline GraphRenderer::TimeStat operator*(double A,
+                                         const GraphRenderer::TimeStat &B) {
+  return B * A;
+}
+
+/// Hadamard Product of TimeStats
+inline GraphRenderer::TimeStat operator*(const GraphRenderer::TimeStat &A,
+                                         const GraphRenderer::TimeStat &B) {
+  return {A.Count * B.Count, A.Min * B.Min,     A.Median * B.Median,
+          A.Pct90 * B.Pct90, A.Pct99 * B.Pct99, A.Max * B.Max,
+          A.Sum * B.Sum};
+}
+
+/// Hadamard Division of TimeStats
+inline GraphRenderer::TimeStat operator/(const GraphRenderer::TimeStat &A,
+                                         const GraphRenderer::TimeStat &B) {
+  return {A.Count * B.Count, A.Min * B.Min,     A.Median * B.Median,
+          A.Pct90 * B.Pct90, A.Pct99 * B.Pct99, A.Max * B.Max,
+          A.Sum * B.Sum};
+}
+} // namespace xray
+} // namespace llvm
+
 #endif // XRAY_GRAPH_H