<div dir="ltr">This was fixed a couple of commits later I think?</div><div class="gmail_extra"><br><br><div class="gmail_quote">On Wed, Feb 5, 2014 at 11:48 PM, Kostya Serebryany <span dir="ltr"><<a href="mailto:kcc@google.com" target="_blank">kcc@google.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">This makes our bootstrap bot sad... <div><a href="http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-bootstrap/builds/2043/steps/check-llvm%20msan/logs/stdio" target="_blank">http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-bootstrap/builds/2043/steps/check-llvm%20msan/logs/stdio</a><br>

</div><div><br></div><div><pre style="font-size:medium;font-family:'Courier New',courier,monotype,monospace"><span>FAIL: LLVM :: Analysis/LazyCallGraph/basic.ll (127 of 9712)
******************** TEST 'LLVM :: Analysis/LazyCallGraph/basic.ll' FAILED ********************
Script:
--
/home/dtoolsbot/build/sanitizer-x86_64-linux-bootstrap/build/llvm_build_msan/./bin/opt -disable-output -passes=print-cg /home/dtoolsbot/build/sanitizer-x86_64-linux-bootstrap/build/llvm/test/Analysis/LazyCallGraph/basic.ll 2>&1 | /home/dtoolsbot/build/sanitizer-x86_64-linux-bootstrap/build/llvm_build_msan/./bin/FileCheck /home/dtoolsbot/build/sanitizer-x86_64-linux-bootstrap/build/llvm/test/Analysis/LazyCallGraph/basic.ll
--
Exit Code: 1

Command Output (stderr):
--
/home/dtoolsbot/build/sanitizer-x86_64-linux-bootstrap/build/llvm/test/Analysis/LazyCallGraph/basic.ll:6:16: error: expected string not found in input
; CHECK-LABEL: Call edges in function: f
               ^
<stdin>:1:1: note: scanning from here
Printing the call graph for module: /home/dtoolsbot/build/sanitizer-x86_64-linux-bootstrap/build/llvm/test/Analysis/LazyCallGraph/basic.ll
^
<stdin>:1:14: note: possible intended match here
Printing the call graph for module: /home/dtoolsbot/build/sanitizer-x86_64-linux-bootstrap/build/llvm/test/Analysis/LazyCallGraph/basic.ll
             ^
</span></pre></div><div><span><br></span></div></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><br><div class="gmail_quote">On Thu, Feb 6, 2014 at 8:37 AM, Chandler Carruth <span dir="ltr"><<a href="mailto:chandlerc@gmail.com" target="_blank">chandlerc@gmail.com</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: chandlerc<br>
Date: Wed Feb  5 22:37:03 2014<br>
New Revision: 200903<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=200903&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=200903&view=rev</a><br>
Log:<br>
[PM] Add a new "lazy" call graph analysis pass for the new pass manager.<br>
<br>
The primary motivation for this pass is to separate the call graph<br>
analysis used by the new pass manager's CGSCC pass management from the<br>
existing call graph analysis pass. That analysis pass is (somewhat<br>
unfortunately) over-constrained by the existing CallGraphSCCPassManager<br>
requirements. Those requirements make it *really* hard to cleanly layer<br>
the needed functionality for the new pass manager on top of the existing<br>
analysis.<br>
<br>
However, there are also a bunch of things that the pass manager would<br>
specifically benefit from doing differently from the existing call graph<br>
analysis, and this new implementation tries to address several of them:<br>
<br>
- Be lazy about scanning function definitions. The existing pass eagerly<br>
  scans the entire module to build the initial graph. This new pass is<br>
  significantly more lazy, and I plan to push this even further to<br>
  maximize locality during CGSCC walks.<br>
- Don't use a single synthetic node to partition functions with an<br>
  indirect call from functions whose address is taken. This node creates<br>
  a huge choke-point which would preclude good parallelization across<br>
  the fanout of the SCC graph when we got to the point of looking at<br>
  such changes to LLVM.<br>
- Use a memory dense and lightweight representation of the call graph<br>
  rather than value handles and tracking call instructions. This will<br>
  require explicit update calls instead of some updates working<br>
  transparently, but should end up being significantly more efficient.<br>
  The explicit update calls ended up being needed in many cases for the<br>
  existing call graph so we don't really lose anything.<br>
- Doesn't explicitly model SCCs and thus doesn't provide an "identity"<br>
  for an SCC which is stable across updates. This is essential for the<br>
  new pass manager to work correctly.<br>
- Only form the graph necessary for traversing all of the functions in<br>
  an SCC friendly order. This is a much simpler graph structure and<br>
  should be more memory dense. It does limit the ways in which it is<br>
  appropriate to use this analysis. I wish I had a better name than<br>
  "call graph". I've commented extensively this aspect.<br>
<br>
This is still very much a WIP, in fact it is really just the initial<br>
bits. But it is about the fourth version of the initial bits that I've<br>
implemented with each of the others running into really frustrating<br>
problms. This looks like it will actually work and I'd like to split the<br>
actual complexity across commits for the sake of my reviewers. =] The<br>
rest of the implementation along with lots of wiring will follow<br>
somewhat more rapidly now that there is a good path forward.<br>
<br>
Naturally, this doesn't impact any of the existing optimizer. This code<br>
is specific to the new pass manager.<br>
<br>
A bunch of thanks are deserved for the various folks that have helped<br>
with the design of this, especially Nick Lewycky who actually sat with<br>
me to go through the fundamentals of the final version here.<br>
<br>
Added:<br>
    llvm/trunk/include/llvm/Analysis/LazyCallGraph.h<br>
    llvm/trunk/lib/Analysis/LazyCallGraph.cpp<br>
    llvm/trunk/test/Analysis/LazyCallGraph/<br>
    llvm/trunk/test/Analysis/LazyCallGraph/basic.ll<br>
Modified:<br>
    llvm/trunk/lib/Analysis/CMakeLists.txt<br>
    llvm/trunk/tools/opt/NewPMDriver.cpp<br>
    llvm/trunk/tools/opt/Passes.cpp<br>
<br>
Added: llvm/trunk/include/llvm/Analysis/LazyCallGraph.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/LazyCallGraph.h?rev=200903&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/LazyCallGraph.h?rev=200903&view=auto</a><br>


==============================================================================<br>
--- llvm/trunk/include/llvm/Analysis/LazyCallGraph.h (added)<br>
+++ llvm/trunk/include/llvm/Analysis/LazyCallGraph.h Wed Feb  5 22:37:03 2014<br>
@@ -0,0 +1,337 @@<br>
+//===- LazyCallGraph.h - Analysis of a Module's call graph ------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+/// \file<br>
+///<br>
+/// Implements a lazy call graph analysis and related passes for the new pass<br>
+/// manager.<br>
+///<br>
+/// NB: This is *not* a traditional call graph! It is a graph which models both<br>
+/// the current calls and potential calls. As a consequence there are many<br>
+/// edges in this call graph that do not correspond to a 'call' or 'invoke'<br>
+/// instruction.<br>
+///<br>
+/// The primary use cases of this graph analysis is to facilitate iterating<br>
+/// across the functions of a module in ways that ensure all callees are<br>
+/// visited prior to a caller (given any SCC constraints), or vice versa. As<br>
+/// such is it particularly well suited to organizing CGSCC optimizations such<br>
+/// as inlining, outlining, argument promotion, etc. That is its primary use<br>
+/// case and motivates the design. It may not be appropriate for other<br>
+/// purposes. The use graph of functions or some other conservative analysis of<br>
+/// call instructions may be interesting for optimizations and subsequent<br>
+/// analyses which don't work in the context of an overly specified<br>
+/// potential-call-edge graph.<br>
+///<br>
+/// To understand the specific rules and nature of this call graph analysis,<br>
+/// see the documentation of the \c LazyCallGraph below.<br>
+///<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLVM_ANALYSIS_LAZY_CALL_GRAPH<br>
+#define LLVM_ANALYSIS_LAZY_CALL_GRAPH<br>
+<br>
+#include "llvm/ADT/DenseMap.h"<br>
+#include "llvm/ADT/PointerUnion.h"<br>
+#include "llvm/ADT/SmallVector.h"<br>
+#include "llvm/ADT/SmallPtrSet.h"<br>
+#include "llvm/ADT/STLExtras.h"<br>
+#include "llvm/IR/Module.h"<br>
+#include "llvm/IR/Function.h"<br>
+#include "llvm/IR/BasicBlock.h"<br>
+#include "llvm/Support/Allocator.h"<br>
+#include <iterator><br>
+<br>
+namespace llvm {<br>
+class ModuleAnalysisManager;<br>
+class PreservedAnalyses;<br>
+class raw_ostream;<br>
+<br>
+/// \brief A lazily constructed view of the call graph of a module.<br>
+///<br>
+/// With the edges of this graph, the motivating constraint that we are<br>
+/// attempting to maintain is that function-local optimization, CGSCC-local<br>
+/// optimizations, and optimizations transforming a pair of functions connected<br>
+/// by an edge in the graph, do not invalidate a bottom-up traversal of the SCC<br>
+/// DAG. That is, no optimizations will delete, remove, or add an edge such<br>
+/// that functions already visited in a bottom-up order of the SCC DAG are no<br>
+/// longer valid to have visited, or such that functions not yet visited in<br>
+/// a bottom-up order of the SCC DAG are not required to have already been<br>
+/// visited.<br>
+///<br>
+/// Within this constraint, the desire is to minimize the merge points of the<br>
+/// SCC DAG. The greater the fanout of the SCC DAG and the fewer merge points<br>
+/// in the SCC DAG, the more independence there is in optimizing within it.<br>
+/// There is a strong desire to enable parallelization of optimizations over<br>
+/// the call graph, and both limited fanout and merge points will (artificially<br>
+/// in some cases) limit the scaling of such an effort.<br>
+///<br>
+/// To this end, graph represents both direct and any potential resolution to<br>
+/// an indirect call edge. Another way to think about it is that it represents<br>
+/// both the direct call edges and any direct call edges that might be formed<br>
+/// through static optimizations. Specifically, it considers taking the address<br>
+/// of a function to be an edge in the call graph because this might be<br>
+/// forwarded to become a direct call by some subsequent function-local<br>
+/// optimization. The result is that the graph closely follows the use-def<br>
+/// edges for functions. Walking "up" the graph can be done by looking at all<br>
+/// of the uses of a function.<br>
+///<br>
+/// The roots of the call graph are the external functions and functions<br>
+/// escaped into global variables. Those functions can be called from outside<br>
+/// of the module or via unknowable means in the IR -- we may not be able to<br>
+/// form even a potential call edge from a function body which may dynamically<br>
+/// load the function and call it.<br>
+///<br>
+/// This analysis still requires updates to remain valid after optimizations<br>
+/// which could potentially change the set of potential callees. The<br>
+/// constraints it operates under only make the traversal order remain valid.<br>
+///<br>
+/// The entire analysis must be re-computed if full interprocedural<br>
+/// optimizations run at any point. For example, globalopt completely<br>
+/// invalidates the information in this analysis.<br>
+///<br>
+/// FIXME: This class is named LazyCallGraph in a lame attempt to distinguish<br>
+/// it from the existing CallGraph. At some point, it is expected that this<br>
+/// will be the only call graph and it will be renamed accordingly.<br>
+class LazyCallGraph {<br>
+public:<br>
+  class Node;<br>
+  typedef SmallVector<PointerUnion<Function *, Node *>, 4> NodeVectorT;<br>
+  typedef SmallVectorImpl<PointerUnion<Function *, Node *> > NodeVectorImplT;<br>
+<br>
+  /// \brief A lazy iterator used for both the entry nodes and child nodes.<br>
+  ///<br>
+  /// When this iterator is dereferenced, if not yet available, a function will<br>
+  /// be scanned for "calls" or uses of functions and its child information<br>
+  /// will be constructed. All of these results are accumulated and cached in<br>
+  /// the graph.<br>
+  class iterator : public std::iterator<std::bidirectional_iterator_tag, Node *,<br>
+                                        ptrdiff_t, Node *, Node *> {<br>
+    friend class LazyCallGraph;<br>
+    friend class LazyCallGraph::Node;<br>
+    typedef std::iterator<std::bidirectional_iterator_tag, Node *, ptrdiff_t,<br>
+                          Node *, Node *> BaseT;<br>
+<br>
+    /// \brief Nonce type to select the constructor for the end iterator.<br>
+    struct IsAtEndT {};<br>
+<br>
+    LazyCallGraph &G;<br>
+    NodeVectorImplT::iterator NI;<br>
+<br>
+    // Build the begin iterator for a node.<br>
+    explicit iterator(LazyCallGraph &G, NodeVectorImplT &Nodes)<br>
+        : G(G), NI(Nodes.begin()) {}<br>
+<br>
+    // Build the end iterator for a node. This is selected purely by overload.<br>
+    iterator(LazyCallGraph &G, NodeVectorImplT &Nodes, IsAtEndT /*Nonce*/)<br>
+        : G(G), NI(Nodes.end()) {}<br>
+<br>
+  public:<br>
+    iterator(const iterator &Arg) : G(Arg.G), NI(Arg.NI) {}<br>
+<br>
+    iterator &operator=(iterator Arg) {<br>
+      std::swap(Arg, *this);<br>
+      return *this;<br>
+    }<br>
+<br>
+    bool operator==(const iterator &Arg) { return NI == Arg.NI; }<br>
+    bool operator!=(const iterator &Arg) { return !operator==(Arg); }<br>
+<br>
+    reference operator*() const {<br>
+      if (NI->is<Node *>())<br>
+        return NI->get<Node *>();<br>
+<br>
+      Function *F = NI->get<Function *>();<br>
+      Node *ChildN = G.get(*F);<br>
+      *NI = ChildN;<br>
+      return ChildN;<br>
+    }<br>
+    pointer operator->() const { return operator*(); }<br>
+<br>
+    iterator &operator++() {<br>
+      ++NI;<br>
+      return *this;<br>
+    }<br>
+    iterator operator++(int) {<br>
+      iterator prev = *this;<br>
+      ++*this;<br>
+      return prev;<br>
+    }<br>
+<br>
+    iterator &operator--() {<br>
+      --NI;<br>
+      return *this;<br>
+    }<br>
+    iterator operator--(int) {<br>
+      iterator next = *this;<br>
+      --*this;<br>
+      return next;<br>
+    }<br>
+  };<br>
+<br>
+  /// \brief Construct a graph for the given module.<br>
+  ///<br>
+  /// This sets up the graph and computes all of the entry points of the graph.<br>
+  /// No function definitions are scanned until their nodes in the graph are<br>
+  /// requested during traversal.<br>
+  LazyCallGraph(Module &M);<br>
+<br>
+  /// \brief Copy constructor.<br>
+  ///<br>
+  /// This does a deep copy of the graph. It does no verification that the<br>
+  /// graph remains valid for the module. It is also relatively expensive.<br>
+  LazyCallGraph(const LazyCallGraph &G);<br>
+<br>
+#if LLVM_HAS_RVALUE_REFERENCES<br>
+  /// \brief Move constructor.<br>
+  ///<br>
+  /// This is a deep move. It leaves G in an undefined but destroyable state.<br>
+  /// Any other operation on G is likely to fail.<br>
+  LazyCallGraph(LazyCallGraph &&G);<br>
+#endif<br>
+<br>
+  iterator begin() { return iterator(*this, EntryNodes); }<br>
+  iterator end() { return iterator(*this, EntryNodes, iterator::IsAtEndT()); }<br>
+<br>
+  /// \brief Lookup a function in the graph which has already been scanned and<br>
+  /// added.<br>
+  Node *lookup(const Function &F) const { return NodeMap.lookup(&F); }<br>
+<br>
+  /// \brief Get a graph node for a given function, scanning it to populate the<br>
+  /// graph data as necessary.<br>
+  Node *get(Function &F) {<br>
+    Node *&N = NodeMap[&F];<br>
+    if (N)<br>
+      return N;<br>
+<br>
+    return insertInto(F, N);<br>
+  }<br>
+<br>
+private:<br>
+  Module &M;<br>
+<br>
+  /// \brief Allocator that holds all the call graph nodes.<br>
+  SpecificBumpPtrAllocator<Node> BPA;<br>
+<br>
+  /// \brief Maps function->node for fast lookup.<br>
+  DenseMap<const Function *, Node *> NodeMap;<br>
+<br>
+  /// \brief The entry nodes to the graph.<br>
+  ///<br>
+  /// These nodes are reachable through "external" means. Put another way, they<br>
+  /// escape at the module scope.<br>
+  NodeVectorT EntryNodes;<br>
+<br>
+  /// \brief Set of the entry nodes to the graph.<br>
+  SmallPtrSet<Function *, 4> EntryNodeSet;<br>
+<br>
+  /// \brief Helper to insert a new function, with an already looked-up entry in<br>
+  /// the NodeMap.<br>
+  Node *insertInto(Function &F, Node *&MappedN);<br>
+<br>
+  /// \brief Helper to copy a node from another graph into this one.<br>
+  Node *copyInto(const Node &OtherN);<br>
+<br>
+#if LLVM_HAS_RVALUE_REFERENCES<br>
+  /// \brief Helper to move a node from another graph into this one.<br>
+  Node *moveInto(Node &&OtherN);<br>
+#endif<br>
+};<br>
+<br>
+/// \brief A node in the call graph.<br>
+///<br>
+/// This represents a single node. It's primary roles are to cache the list of<br>
+/// callees, de-duplicate and provide fast testing of whether a function is<br>
+/// a callee, and facilitate iteration of child nodes in the graph.<br>
+class LazyCallGraph::Node {<br>
+  friend LazyCallGraph;<br>
+<br>
+  LazyCallGraph &G;<br>
+  Function &F;<br>
+  mutable NodeVectorT Callees;<br>
+  SmallPtrSet<Function *, 4> CalleeSet;<br>
+<br>
+  /// \brief Basic constructor implements the scanning of F into Callees and<br>
+  /// CalleeSet.<br>
+  Node(LazyCallGraph &G, Function &F);<br>
+<br>
+  /// \brief Constructor used when copying a node from one graph to another.<br>
+  Node(LazyCallGraph &G, const Node &OtherN);<br>
+<br>
+#if LLVM_HAS_RVALUE_REFERENCES<br>
+  /// \brief Constructor used when moving a node from one graph to another.<br>
+  Node(LazyCallGraph &G, Node &&OtherN);<br>
+#endif<br>
+<br>
+public:<br>
+  typedef LazyCallGraph::iterator iterator;<br>
+<br>
+  Function &getFunction() const {<br>
+    return F;<br>
+  };<br>
+<br>
+  iterator begin() const { return iterator(G, Callees); }<br>
+  iterator end() const { return iterator(G, Callees, iterator::IsAtEndT()); }<br>
+<br>
+  /// Equality is defined as address equality.<br>
+  bool operator==(const Node &N) const { return this == &N; }<br>
+  bool operator!=(const Node &N) const { return !operator==(N); }<br>
+};<br>
+<br>
+// Provide GraphTraits specializations for call graphs.<br>
+template <> struct GraphTraits<LazyCallGraph::Node *> {<br>
+  typedef LazyCallGraph::Node NodeType;<br>
+  typedef LazyCallGraph::iterator ChildIteratorType;<br>
+<br>
+  static NodeType *getEntryNode(NodeType *N) { return N; }<br>
+  static ChildIteratorType child_begin(NodeType *N) { return N->begin(); }<br>
+  static ChildIteratorType child_end(NodeType *N) { return N->end(); }<br>
+};<br>
+template <> struct GraphTraits<LazyCallGraph *> {<br>
+  typedef LazyCallGraph::Node NodeType;<br>
+  typedef LazyCallGraph::iterator ChildIteratorType;<br>
+<br>
+  static NodeType *getEntryNode(NodeType *N) { return N; }<br>
+  static ChildIteratorType child_begin(NodeType *N) { return N->begin(); }<br>
+  static ChildIteratorType child_end(NodeType *N) { return N->end(); }<br>
+};<br>
+<br>
+/// \brief An analysis pass which computes the call graph for a module.<br>
+class LazyCallGraphAnalysis {<br>
+public:<br>
+  /// \brief Inform generic clients of the result type.<br>
+  typedef LazyCallGraph Result;<br>
+<br>
+  static void *ID() { return (void *)&PassID; }<br>
+<br>
+  /// \brief Compute the \c LazyCallGraph for a the module \c M.<br>
+  ///<br>
+  /// This just builds the set of entry points to the call graph. The rest is<br>
+  /// built lazily as it is walked.<br>
+  LazyCallGraph run(Module *M) { return LazyCallGraph(*M); }<br>
+<br>
+private:<br>
+  static char PassID;<br>
+};<br>
+<br>
+/// \brief A pass which prints the call graph to a \c raw_ostream.<br>
+///<br>
+/// This is primarily useful for testing the analysis.<br>
+class LazyCallGraphPrinterPass {<br>
+  raw_ostream &OS;<br>
+<br>
+public:<br>
+  explicit LazyCallGraphPrinterPass(raw_ostream &OS);<br>
+<br>
+  PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM);<br>
+<br>
+  static StringRef name() { return "LazyCallGraphPrinterPass"; }<br>
+};<br>
+<br>
+}<br>
+<br>
+#endif<br>
<br>
Modified: llvm/trunk/lib/Analysis/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CMakeLists.txt?rev=200903&r1=200902&r2=200903&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CMakeLists.txt?rev=200903&r1=200902&r2=200903&view=diff</a><br>


==============================================================================<br>
--- llvm/trunk/lib/Analysis/CMakeLists.txt (original)<br>
+++ llvm/trunk/lib/Analysis/CMakeLists.txt Wed Feb  5 22:37:03 2014<br>
@@ -23,6 +23,7 @@ add_llvm_library(LLVMAnalysis<br>
   InstructionSimplify.cpp<br>
   Interval.cpp<br>
   IntervalPartition.cpp<br>
+  LazyCallGraph.cpp<br>
   LazyValueInfo.cpp<br>
   LibCallAliasAnalysis.cpp<br>
   LibCallSemantics.cpp<br>
<br>
Added: llvm/trunk/lib/Analysis/LazyCallGraph.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/LazyCallGraph.cpp?rev=200903&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/LazyCallGraph.cpp?rev=200903&view=auto</a><br>


==============================================================================<br>
--- llvm/trunk/lib/Analysis/LazyCallGraph.cpp (added)<br>
+++ llvm/trunk/lib/Analysis/LazyCallGraph.cpp Wed Feb  5 22:37:03 2014<br>
@@ -0,0 +1,195 @@<br>
+//===- LazyCallGraph.cpp - Analysis of a Module's call graph --------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "llvm/Analysis/LazyCallGraph.h"<br>
+#include "llvm/ADT/SCCIterator.h"<br>
+#include "llvm/IR/Instructions.h"<br>
+#include "llvm/IR/PassManager.h"<br>
+#include "llvm/Support/CallSite.h"<br>
+#include "llvm/Support/raw_ostream.h"<br>
+#include "llvm/InstVisitor.h"<br>
+<br>
+using namespace llvm;<br>
+<br>
+static void findCallees(<br>
+    SmallVectorImpl<Constant *> &Worklist, SmallPtrSetImpl<Constant *> &Visited,<br>
+    SmallVectorImpl<PointerUnion<Function *, LazyCallGraph::Node *> > &Callees,<br>
+    SmallPtrSetImpl<Function *> &CalleeSet) {<br>
+  while (!Worklist.empty()) {<br>
+    Constant *C = Worklist.pop_back_val();<br>
+<br>
+    if (Function *F = dyn_cast<Function>(C)) {<br>
+      // Note that we consider *any* function with a definition to be a viable<br>
+      // edge. Even if the function's definition is subject to replacement by<br>
+      // some other module (say, a weak definition) there may still be<br>
+      // optimizations which essentially speculate based on the definition and<br>
+      // a way to check that the specific definition is in fact the one being<br>
+      // used. For example, this could be done by moving the weak definition to<br>
+      // a strong (internal) definition and making the weak definition be an<br>
+      // alias. Then a test of the address of the weak function against the new<br>
+      // strong definition's address would be an effective way to determine the<br>
+      // safety of optimizing a direct call edge.<br>
+      if (!F->isDeclaration() && CalleeSet.insert(F))<br>
+          Callees.push_back(F);<br>
+      continue;<br>
+    }<br>
+<br>
+    for (User::value_op_iterator OI = C->value_op_begin(),<br>
+                                 OE = C->value_op_end();<br>
+         OI != OE; ++OI)<br>
+      if (Visited.insert(cast<Constant>(*OI)))<br>
+        Worklist.push_back(cast<Constant>(*OI));<br>
+  }<br>
+}<br>
+<br>
+LazyCallGraph::Node::Node(LazyCallGraph &G, Function &F) : G(G), F(F) {<br>
+  SmallVector<Constant *, 16> Worklist;<br>
+  SmallPtrSet<Constant *, 16> Visited;<br>
+  // Find all the potential callees in this function. First walk the<br>
+  // instructions and add every operand which is a constant to the worklist.<br>
+  for (Function::iterator BBI = F.begin(), BBE = F.end(); BBI != BBE; ++BBI)<br>
+    for (BasicBlock::iterator II = BBI->begin(), IE = BBI->end(); II != IE;<br>
+         ++II)<br>
+      for (User::value_op_iterator OI = II->value_op_begin(),<br>
+                                   OE = II->value_op_end();<br>
+           OI != OE; ++OI)<br>
+        if (Constant *C = dyn_cast<Constant>(*OI))<br>
+          if (Visited.insert(C))<br>
+            Worklist.push_back(C);<br>
+<br>
+  // We've collected all the constant (and thus potentially function or<br>
+  // function containing) operands to all of the instructions in the function.<br>
+  // Process them (recursively) collecting every function found.<br>
+  findCallees(Worklist, Visited, Callees, CalleeSet);<br>
+}<br>
+<br>
+LazyCallGraph::Node::Node(LazyCallGraph &G, const Node &OtherN)<br>
+    : G(G), F(OtherN.F), CalleeSet(OtherN.CalleeSet) {<br>
+  // Loop over the other node's callees, adding the Function*s to our list<br>
+  // directly, and recursing to add the Node*s.<br>
+  Callees.reserve(OtherN.Callees.size());<br>
+  for (NodeVectorImplT::iterator OI = OtherN.Callees.begin(),<br>
+                                 OE = OtherN.Callees.end();<br>
+       OI != OE; ++OI)<br>
+    if (Function *Callee = OI->dyn_cast<Function *>())<br>
+      Callees.push_back(Callee);<br>
+    else<br>
+      Callees.push_back(G.copyInto(*OI->get<Node *>()));<br>
+}<br>
+<br>
+#if LLVM_HAS_RVALUE_REFERENCES<br>
+LazyCallGraph::Node::Node(LazyCallGraph &G, Node &&OtherN)<br>
+    : G(G), F(OtherN.F), Callees(std::move(OtherN.Callees)),<br>
+      CalleeSet(std::move(OtherN.CalleeSet)) {<br>
+  // Loop over our Callees. They've been moved from another node, but we need<br>
+  // to move the Node*s to live under our bump ptr allocator.<br>
+  for (NodeVectorImplT::iterator CI = Callees.begin(), CE = Callees.end();<br>
+       CI != CE; ++CI)<br>
+    if (Node *ChildN = CI->dyn_cast<Node *>())<br>
+      *CI = G.moveInto(std::move(*ChildN));<br>
+}<br>
+#endif<br>
+<br>
+LazyCallGraph::LazyCallGraph(Module &M) : M(M) {<br>
+  for (Module::iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI)<br>
+    if (!FI->isDeclaration() && !FI->hasLocalLinkage())<br>
+      if (EntryNodeSet.insert(&*FI))<br>
+        EntryNodes.push_back(&*FI);<br>
+<br>
+  // Now add entry nodes for functions reachable via initializers to globals.<br>
+  SmallVector<Constant *, 16> Worklist;<br>
+  SmallPtrSet<Constant *, 16> Visited;<br>
+  for (Module::global_iterator GI = M.global_begin(), GE = M.global_end(); GI != GE; ++GI)<br>
+    if (GI->hasInitializer())<br>
+      if (Visited.insert(GI->getInitializer()))<br>
+        Worklist.push_back(GI->getInitializer());<br>
+<br>
+  findCallees(Worklist, Visited, EntryNodes, EntryNodeSet);<br>
+}<br>
+<br>
+LazyCallGraph::LazyCallGraph(const LazyCallGraph &G)<br>
+    : M(G.M), EntryNodeSet(G.EntryNodeSet) {<br>
+  EntryNodes.reserve(EntryNodes.size());<br>
+  for (NodeVectorImplT::iterator EI = EntryNodes.begin(),<br>
+                                 EE = EntryNodes.end();<br>
+       EI != EE; ++EI)<br>
+    if (Function *Callee = EI->dyn_cast<Function *>())<br>
+      EntryNodes.push_back(Callee);<br>
+    else<br>
+      EntryNodes.push_back(copyInto(*EI->get<Node *>()));<br>
+}<br>
+<br>
+#if LLVM_HAS_RVALUE_REFERENCES<br>
+// FIXME: This would be crazy simpler if BumpPtrAllocator were movable without<br>
+// invalidating any of the allocated memory. We should make that be the case at<br>
+// some point and delete this.<br>
+LazyCallGraph::LazyCallGraph(LazyCallGraph &&G)<br>
+    : M(G.M), EntryNodes(std::move(G.EntryNodes)),<br>
+      EntryNodeSet(std::move(G.EntryNodeSet)) {<br>
+  // Loop over our EntryNodes. They've been moved from another graph, but we<br>
+  // need to move the Node*s to live under our bump ptr allocator.<br>
+  for (NodeVectorImplT::iterator EI = EntryNodes.begin(), EE = EntryNodes.end();<br>
+       EI != EE; ++EI)<br>
+    if (Node *EntryN = EI->dyn_cast<Node *>())<br>
+      *EI = G.moveInto(std::move(*EntryN));<br>
+}<br>
+#endif<br>
+<br>
+LazyCallGraph::Node *LazyCallGraph::insertInto(Function &F, Node *&MappedN) {<br>
+  return new (MappedN = BPA.Allocate()) Node(*this, F);<br>
+}<br>
+<br>
+LazyCallGraph::Node *LazyCallGraph::copyInto(const Node &OtherN) {<br>
+  Node *&N = NodeMap[&OtherN.F];<br>
+  if (N)<br>
+    return N;<br>
+<br>
+  return new (N = BPA.Allocate()) Node(*this, OtherN);<br>
+}<br>
+<br>
+#if LLVM_HAS_RVALUE_REFERENCES<br>
+LazyCallGraph::Node *LazyCallGraph::moveInto(Node &&OtherN) {<br>
+  Node *&N = NodeMap[&OtherN.F];<br>
+  if (N)<br>
+    return N;<br>
+<br>
+  return new (N = BPA.Allocate()) Node(*this, std::move(OtherN));<br>
+}<br>
+#endif<br>
+<br>
+char LazyCallGraphAnalysis::PassID;<br>
+<br>
+LazyCallGraphPrinterPass::LazyCallGraphPrinterPass(raw_ostream &OS) : OS(OS) {}<br>
+<br>
+static void printNodes(raw_ostream &OS, LazyCallGraph::Node &N,<br>
+                       SmallPtrSetImpl<LazyCallGraph::Node *> &Printed) {<br>
+  // Recurse depth first through the nodes.<br>
+  for (LazyCallGraph::iterator I = N.begin(), E = N.end(); I != E; ++I)<br>
+    if (Printed.insert(*I))<br>
+      printNodes(OS, **I, Printed);<br>
+<br>
+  OS << "  Call edges in function: " << N.getFunction().getName() << "\n";<br>
+  for (LazyCallGraph::iterator I = N.begin(), E = N.end(); I != E; ++I)<br>
+    OS << "    -> " << I->getFunction().getName() << "\n";<br>
+<br>
+  OS << "\n";<br>
+}<br>
+<br>
+PreservedAnalyses LazyCallGraphPrinterPass::run(Module *M, ModuleAnalysisManager *AM) {<br>
+  LazyCallGraph &G = AM->getResult<LazyCallGraphAnalysis>(M);<br>
+<br>
+  OS << "Printing the call graph for module: " << M->getModuleIdentifier() << "\n\n";<br>
+<br>
+  SmallPtrSet<LazyCallGraph::Node *, 16> Printed;<br>
+  for (LazyCallGraph::iterator I = G.begin(), E = G.end(); I != E; ++I)<br>
+    if (Printed.insert(*I))<br>
+      printNodes(OS, **I, Printed);<br>
+<br>
+  return PreservedAnalyses::all();<br>
+}<br>
<br>
Added: llvm/trunk/test/Analysis/LazyCallGraph/basic.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/LazyCallGraph/basic.ll?rev=200903&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/LazyCallGraph/basic.ll?rev=200903&view=auto</a><br>


==============================================================================<br>
--- llvm/trunk/test/Analysis/LazyCallGraph/basic.ll (added)<br>
+++ llvm/trunk/test/Analysis/LazyCallGraph/basic.ll Wed Feb  5 22:37:03 2014<br>
@@ -0,0 +1,126 @@<br>
+; RUN: opt -disable-output -passes=print-cg %s 2>&1 | FileCheck %s<br>
+;<br>
+; Basic validation of the call graph analysis used in the new pass manager.<br>
+<br>
+define void @f() {<br>
+; CHECK-LABEL: Call edges in function: f<br>
+; CHECK-NOT: -><br>
+<br>
+entry:<br>
+  ret void<br>
+}<br>
+<br>
+; A bunch more functions just to make it easier to test several call edges at once.<br>
+define void @f1() {<br>
+  ret void<br>
+}<br>
+define void @f2() {<br>
+  ret void<br>
+}<br>
+define void @f3() {<br>
+  ret void<br>
+}<br>
+define void @f4() {<br>
+  ret void<br>
+}<br>
+define void @f5() {<br>
+  ret void<br>
+}<br>
+define void @f6() {<br>
+  ret void<br>
+}<br>
+define void @f7() {<br>
+  ret void<br>
+}<br>
+define void @f8() {<br>
+  ret void<br>
+}<br>
+define void @f9() {<br>
+  ret void<br>
+}<br>
+define void @f10() {<br>
+  ret void<br>
+}<br>
+define void @f11() {<br>
+  ret void<br>
+}<br>
+define void @f12() {<br>
+  ret void<br>
+}<br>
+<br>
+declare i32 @__gxx_personality_v0(...)<br>
+<br>
+define void @test0() {<br>
+; CHECK-LABEL: Call edges in function: test0<br>
+; CHECK-NEXT: -> f<br>
+; CHECK-NOT: -><br>
+<br>
+entry:<br>
+  call void @f()<br>
+  call void @f()<br>
+  call void @f()<br>
+  call void @f()<br>
+  ret void<br>
+}<br>
+<br>
+define void ()* @test1(void ()** %x) {<br>
+; CHECK-LABEL: Call edges in function: test1<br>
+; CHECK-NEXT: -> f12<br>
+; CHECK-NEXT: -> f11<br>
+; CHECK-NEXT: -> f10<br>
+; CHECK-NEXT: -> f7<br>
+; CHECK-NEXT: -> f9<br>
+; CHECK-NEXT: -> f8<br>
+; CHECK-NEXT: -> f6<br>
+; CHECK-NEXT: -> f5<br>
+; CHECK-NEXT: -> f4<br>
+; CHECK-NEXT: -> f3<br>
+; CHECK-NEXT: -> f2<br>
+; CHECK-NEXT: -> f1<br>
+; CHECK-NOT: -><br>
+<br>
+entry:<br>
+  br label %next<br>
+<br>
+dead:<br>
+  br label %next<br>
+<br>
+next:<br>
+  phi void ()* [ @f1, %entry ], [ @f2, %dead ]<br>
+  select i1 true, void ()* @f3, void ()* @f4<br>
+  store void ()* @f5, void ()** %x<br>
+  call void @f6()<br>
+  call void (void ()*, void ()*)* bitcast (void ()* @f7 to void (void ()*, void ()*)*)(void ()* @f8, void ()* @f9)<br>
+  invoke void @f10() to label %exit unwind label %unwind<br>
+<br>
+exit:<br>
+  ret void ()* @f11<br>
+<br>
+unwind:<br>
+  %res = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0<br>
+          cleanup<br>
+  resume { i8*, i32 } { i8* bitcast (void ()* @f12 to i8*), i32 42 }<br>
+}<br>
+<br>
+@g = global void ()* @f1<br>
+@g1 = global [4 x void ()*] [void ()* @f2, void ()* @f3, void ()* @f4, void ()* @f5]<br>
+@g2 = global {i8, void ()*, i8} {i8 1, void ()* @f6, i8 2}<br>
+@h = constant void ()* @f7<br>
+<br>
+define void @test2() {<br>
+; CHECK-LABEL: Call edges in function: test2<br>
+; CHECK-NEXT: -> f7<br>
+; CHECK-NEXT: -> f6<br>
+; CHECK-NEXT: -> f5<br>
+; CHECK-NEXT: -> f4<br>
+; CHECK-NEXT: -> f3<br>
+; CHECK-NEXT: -> f2<br>
+; CHECK-NEXT: -> f1<br>
+; CHECK-NOT: -><br>
+<br>
+  load i8** bitcast (void ()** @g to i8**)<br>
+  load i8** bitcast (void ()** getelementptr ([4 x void ()*]* @g1, i32 0, i32 2) to i8**)<br>
+  load i8** bitcast (void ()** getelementptr ({i8, void ()*, i8}* @g2, i32 0, i32 1) to i8**)<br>
+  load i8** bitcast (void ()** @h to i8**)<br>
+  ret void<br>
+}<br>
<br>
Modified: llvm/trunk/tools/opt/NewPMDriver.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/opt/NewPMDriver.cpp?rev=200903&r1=200902&r2=200903&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/opt/NewPMDriver.cpp?rev=200903&r1=200902&r2=200903&view=diff</a><br>


==============================================================================<br>
--- llvm/trunk/tools/opt/NewPMDriver.cpp (original)<br>
+++ llvm/trunk/tools/opt/NewPMDriver.cpp Wed Feb  5 22:37:03 2014<br>
@@ -16,6 +16,7 @@<br>
 #include "NewPMDriver.h"<br>
 #include "Passes.h"<br>
 #include "llvm/ADT/StringRef.h"<br>
+#include "llvm/Analysis/LazyCallGraph.h"<br>
 #include "llvm/Bitcode/BitcodeWriterPass.h"<br>
 #include "llvm/IR/IRPrintingPasses.h"<br>
 #include "llvm/IR/LLVMContext.h"<br>
@@ -35,6 +36,10 @@ bool llvm::runPassPipeline(StringRef Arg<br>
   FunctionAnalysisManager FAM;<br>
   ModuleAnalysisManager MAM;<br>
<br>
+  // FIXME: Lift this registration of analysis passes into a .def file adjacent<br>
+  // to the one used to associate names with passes.<br>
+  MAM.registerPass(LazyCallGraphAnalysis());<br>
+<br>
   // Cross register the analysis managers through their proxies.<br>
   MAM.registerPass(FunctionAnalysisManagerModuleProxy(FAM));<br>
   FAM.registerPass(ModuleAnalysisManagerFunctionProxy(MAM));<br>
<br>
Modified: llvm/trunk/tools/opt/Passes.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/opt/Passes.cpp?rev=200903&r1=200902&r2=200903&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/opt/Passes.cpp?rev=200903&r1=200902&r2=200903&view=diff</a><br>


==============================================================================<br>
--- llvm/trunk/tools/opt/Passes.cpp (original)<br>
+++ llvm/trunk/tools/opt/Passes.cpp Wed Feb  5 22:37:03 2014<br>
@@ -15,6 +15,7 @@<br>
 //===----------------------------------------------------------------------===//<br>
<br>
 #include "Passes.h"<br>
+#include "llvm/Analysis/LazyCallGraph.h"<br>
 #include "llvm/IR/IRPrintingPasses.h"<br>
 #include "llvm/IR/PassManager.h"<br>
 #include "llvm/IR/Verifier.h"<br>
@@ -43,6 +44,7 @@ struct NoOpFunctionPass {<br>
 static bool isModulePassName(StringRef Name) {<br>
   if (Name == "no-op-module") return true;<br>
   if (Name == "print") return true;<br>
+  if (Name == "print-cg") return true;<br>
<br>
   return false;<br>
 }<br>
@@ -63,6 +65,10 @@ static bool parseModulePassName(ModulePa<br>
     MPM.addPass(PrintModulePass(dbgs()));<br>
     return true;<br>
   }<br>
+  if (Name == "print-cg") {<br>
+    MPM.addPass(LazyCallGraphPrinterPass(dbgs()));<br>
+    return true;<br>
+  }<br>
   return false;<br>
 }<br>
<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>
</div></div><br>_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
<br></blockquote></div><br></div>