<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Sorry for the trouble and thanks for reverting!<div class=""><br class=""></div><div class="">I’ll take a look.</div><div class=""><br class=""></div><div class="">Mark<br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Aug 16, 2019, at 3:58 AM, Benjamin Kramer <<a href="mailto:benny.kra@gmail.com" class="">benny.kra@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">This crashes clang on the attached test case, I reverted the change in r369096.<div class=""><br class=""></div><div class="">$ clang -O3 -c -fexperimental-new-pass-manager -fprofile-generate t.ii</div><div class="">clang: llvm/lib/Analysis/LazyCallGraph.cpp:1535: void llvm::LazyCallGraph::removeDeadFunction(llvm::Function &): Assertion `RC.size() == 1 && "Dead functions must be in a singular RefSCC"' failed.<br class="">Stack dump:<br class="">0.      Program arguments: clang -cc1 -triple x86_64-unknown-linux-gnu -emit-obj -disable-free -main-file-name t.ii -mrelocation-model static -mthread-model posix -mframe-pointer=none -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -fprofile-instrument=llvm -coverage-notes-file /tmp/reduce/t.gcno -resource-dir lib/clang/10.0.0 -O3 -fdeprecated-macro -fdebug-compilation-dir /tmp/reduce -ferror-limit 19 -fmessage-length 0 -fexperimental-new-pass-manager -fobjc-runtime=gcc -fcxx-exceptions -fexceptions -fdiagnostics-show-option -fcolor-diagnostics -vectorize-loops -vectorize-slp -faddrsig -o t.o -x c++-cpp-output t.ii <br class="">1.     <eof> parser at end of file<br class="">2.        Optimizer<br class=""></div></div><br class=""><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Aug 15, 2019 at 7:46 PM Mark Lacey via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org" class="">llvm-commits@lists.llvm.org</a>> wrote:<br class=""></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Author: rudkx<br class="">
Date: Thu Aug 15 10:47:53 2019<br class="">
New Revision: 369025<br class="">
<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=369025&view=rev" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project?rev=369025&view=rev</a><br class="">
Log:<br class="">
[CallGraph] Refine call graph for indirect calls with !callees metadata<br class="">
<br class="">
For indirect call sites having a small set of possible callees,<br class="">
!callees metadata can be used to indicate what those callees are.<br class="">
This patch updates the call graph and lazy call graph analyses so<br class="">
that they consider this metadata when encountering call sites. For<br class="">
the call graph, it adds a new external call graph node to the graph<br class="">
for each unique !callees metadata node. A call graph edge connects<br class="">
an indirect call site with the external node associated with the<br class="">
!callees metadata that is attached to it. And there is an edge from<br class="">
this external node to each of the callees indicated by the metadata.<br class="">
Similarly, for the lazy call graph, the patch adds Ref edges from a<br class="">
caller to the possible callees indicated by the metadata.<br class="">
<br class="">
The primary purpose of the patch is to facilitate iterating over the<br class="">
functions in a module such that all of the callees indicated by a<br class="">
given !callees metadata node will be visited prior to the functions<br class="">
containing call sites annotated by that node. This property is<br class="">
required by optimizations performing a bottom-up traversal of the<br class="">
SCC DAG. For example, the inliner can be made to inline through an<br class="">
indirect call. If the call site is annotated with !callees metadata,<br class="">
this patch ensures that the inliner will have visited all of the<br class="">
callees prior to the caller, allowing it to reliably compute the<br class="">
cost of inlining one or more of the potential callees.<br class="">
<br class="">
Original patch by @mssimpso. I've made some small changes to get it<br class="">
to apply, build, and pass tests on the top of tree, as well as<br class="">
some minor tweaks to formatting and functionality.<br class="">
<br class="">
Subscribers: mehdi_amini, hiraditya, llvm-commits, mssimpso<br class="">
<br class="">
Tags: #llvm<br class="">
<br class="">
Differential Revision: <a href="https://reviews.llvm.org/D39339" rel="noreferrer" target="_blank" class="">https://reviews.llvm.org/D39339</a><br class="">
<br class="">
Added:<br class="">
    llvm/trunk/test/Analysis/CallGraph/callees-metadata.ll<br class="">
    llvm/trunk/test/Analysis/LazyCallGraph/callees-metadata.ll<br class="">
Modified:<br class="">
    llvm/trunk/include/llvm/Analysis/CallGraph.h<br class="">
    llvm/trunk/include/llvm/IR/CallSite.h<br class="">
    llvm/trunk/lib/Analysis/CGSCCPassManager.cpp<br class="">
    llvm/trunk/lib/Analysis/CallGraph.cpp<br class="">
    llvm/trunk/lib/Analysis/LazyCallGraph.cpp<br class="">
    llvm/trunk/test/Analysis/CallGraph/non-leaf-intrinsics.ll<br class="">
<br class="">
Modified: llvm/trunk/include/llvm/Analysis/CallGraph.h<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/CallGraph.h?rev=369025&r1=369024&r2=369025&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/CallGraph.h?rev=369025&r1=369024&r2=369025&view=diff</a><br class="">
==============================================================================<br class="">
--- llvm/trunk/include/llvm/Analysis/CallGraph.h (original)<br class="">
+++ llvm/trunk/include/llvm/Analysis/CallGraph.h Thu Aug 15 10:47:53 2019<br class="">
@@ -46,6 +46,7 @@<br class="">
 #define LLVM_ANALYSIS_CALLGRAPH_H<br class="">
<br class="">
 #include "llvm/ADT/GraphTraits.h"<br class="">
+#include "llvm/ADT/MapVector.h"<br class="">
 #include "llvm/ADT/STLExtras.h"<br class="">
 #include "llvm/IR/Function.h"<br class="">
 #include "llvm/IR/InstrTypes.h"<br class="">
@@ -76,9 +77,22 @@ class CallGraph {<br class="">
   using FunctionMapTy =<br class="">
       std::map<const Function *, std::unique_ptr<CallGraphNode>>;<br class="">
<br class="">
+  /// \brief A type for maintaining dummy nodes.<br class="">
+  ///<br class="">
+  /// Dummy nodes (i.e., nodes having a null function) include, for example,<br class="">
+  /// those created to represent !callees metadata. We use a void pointer as<br class="">
+  /// the key to allow for various kinds of dummy nodes. We use a MapVector to<br class="">
+  /// ensure a deterministic iteration order (there's no good way to sort dummy<br class="">
+  /// nodes). A deterministic iteration order is primarily useful for printing.<br class="">
+  using DummyNodeMapTy =<br class="">
+      MapVector<const MDNode *, std::unique_ptr<CallGraphNode>>;<br class="">
+<br class="">
   /// A map from \c Function* to \c CallGraphNode*.<br class="">
   FunctionMapTy FunctionMap;<br class="">
<br class="">
+  /// \brief A map for maintaining dummy nodes.<br class="">
+  DummyNodeMapTy DummyNodeMap;<br class="">
+<br class="">
   /// This node has edges to all external functions and those internal<br class="">
   /// functions that have their address taken.<br class="">
   CallGraphNode *ExternalCallingNode;<br class="">
@@ -155,6 +169,9 @@ public:<br class="">
   /// Similar to operator[], but this will insert a new CallGraphNode for<br class="">
   /// \c F if one does not already exist.<br class="">
   CallGraphNode *getOrInsertFunction(const Function *F);<br class="">
+<br class="">
+  /// \brief Return the dummy node associated with the given metadata node.<br class="">
+  CallGraphNode *getOrInsertNodeForCalleesMD(MDNode *Callees);<br class="">
 };<br class="">
<br class="">
 /// A node in the call graph for a module.<br class="">
<br class="">
Modified: llvm/trunk/include/llvm/IR/CallSite.h<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/CallSite.h?rev=369025&r1=369024&r2=369025&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/CallSite.h?rev=369025&r1=369024&r2=369025&view=diff</a><br class="">
==============================================================================<br class="">
--- llvm/trunk/include/llvm/IR/CallSite.h (original)<br class="">
+++ llvm/trunk/include/llvm/IR/CallSite.h Thu Aug 15 10:47:53 2019<br class="">
@@ -663,6 +663,30 @@ public:<br class="">
     return false;<br class="">
   }<br class="">
<br class="">
+  /// Return the set of functions this call site is known to call. For direct<br class="">
+  /// calls, the returned set contains the called function. For indirect calls,<br class="">
+  /// this function collects known callees from !callees metadata, if present.<br class="">
+  SmallVector<FunTy *, 1> getKnownCallees() {<br class="">
+    SmallVector<FunTy *, 1> Callees;<br class="">
+<br class="">
+    if (getCalledFunction()) {<br class="">
+      // If the call site is direct, just add the called function to the set.<br class="">
+      Callees.push_back(getCalledFunction());<br class="">
+      return Callees;<br class="">
+    }<br class="">
+<br class="">
+    InstrTy *Inst = getInstruction();<br class="">
+    if (auto *Node = Inst->getMetadata(LLVMContext::MD_callees)) {<br class="">
+      // Otherwise, if the call site is indirect, collect the known callees from<br class="">
+      // !callees metadata if present.<br class="">
+      for (const MDOperand &Op : Node->operands())<br class="">
+        if (auto *MDConstant = mdconst::extract_or_null<Constant>(Op))<br class="">
+          Callees.push_back(cast<FunTy>(MDConstant));<br class="">
+    }<br class="">
+<br class="">
+    return Callees;<br class="">
+  }<br class="">
+<br class="">
 private:<br class="">
   IterTy getCallee() const {<br class="">
     return cast<CallBase>(getInstruction())->op_end() - 1;<br class="">
<br class="">
Modified: llvm/trunk/lib/Analysis/CGSCCPassManager.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CGSCCPassManager.cpp?rev=369025&r1=369024&r2=369025&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CGSCCPassManager.cpp?rev=369025&r1=369024&r2=369025&view=diff</a><br class="">
==============================================================================<br class="">
--- llvm/trunk/lib/Analysis/CGSCCPassManager.cpp (original)<br class="">
+++ llvm/trunk/lib/Analysis/CGSCCPassManager.cpp Thu Aug 15 10:47:53 2019<br class="">
@@ -449,7 +449,7 @@ LazyCallGraph::SCC &llvm::updateCGAndAna<br class="">
   // irrelevant.<br class="">
   for (Instruction &I : instructions(F))<br class="">
     if (auto CS = CallSite(&I))<br class="">
-      if (Function *Callee = CS.getCalledFunction())<br class="">
+      for (Function *Callee : CS.getKnownCallees()) {<br class="">
         if (Visited.insert(Callee).second && !Callee->isDeclaration()) {<br class="">
           Node &CalleeN = *G.lookup(*Callee);<br class="">
           Edge *E = N->lookup(CalleeN);<br class="">
@@ -467,6 +467,7 @@ LazyCallGraph::SCC &llvm::updateCGAndAna<br class="">
           if (!E->isCall())<br class="">
             PromotedRefTargets.insert(&CalleeN);<br class="">
         }<br class="">
+      }<br class="">
<br class="">
   // Now walk all references.<br class="">
   for (Instruction &I : instructions(F))<br class="">
<br class="">
Modified: llvm/trunk/lib/Analysis/CallGraph.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CallGraph.cpp?rev=369025&r1=369024&r2=369025&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CallGraph.cpp?rev=369025&r1=369024&r2=369025&view=diff</a><br class="">
==============================================================================<br class="">
--- llvm/trunk/lib/Analysis/CallGraph.cpp (original)<br class="">
+++ llvm/trunk/lib/Analysis/CallGraph.cpp Thu Aug 15 10:47:53 2019<br class="">
@@ -37,6 +37,7 @@ CallGraph::CallGraph(Module &M)<br class="">
<br class="">
 CallGraph::CallGraph(CallGraph &&Arg)<br class="">
     : M(Arg.M), FunctionMap(std::move(Arg.FunctionMap)),<br class="">
+      DummyNodeMap(std::move(Arg.DummyNodeMap)),<br class="">
       ExternalCallingNode(Arg.ExternalCallingNode),<br class="">
       CallsExternalNode(std::move(Arg.CallsExternalNode)) {<br class="">
   Arg.FunctionMap.clear();<br class="">
@@ -53,6 +54,8 @@ CallGraph::~CallGraph() {<br class="">
 #ifndef NDEBUG<br class="">
   for (auto &I : FunctionMap)<br class="">
     I.second->allReferencesDropped();<br class="">
+  for (auto &N : DummyNodeMap)<br class="">
+    N.second->allReferencesDropped();<br class="">
 #endif<br class="">
 }<br class="">
<br class="">
@@ -74,7 +77,14 @@ void CallGraph::addToCallGraph(Function<br class="">
     for (Instruction &I : BB) {<br class="">
       if (auto *Call = dyn_cast<CallBase>(&I)) {<br class="">
         const Function *Callee = Call->getCalledFunction();<br class="">
-        if (!Callee || !Intrinsic::isLeaf(Callee->getIntrinsicID()))<br class="">
+        MDNode *CalleesMD = I.getMetadata(LLVMContext::MD_callees);<br class="">
+        if (!Callee && CalleesMD)<br class="">
+          // If an indirect call site has !callees metadata indicating its<br class="">
+          // possible callees, we add an edge from the call site to a dummy<br class="">
+          // node. When we construct the dummy node, we add edges from it to<br class="">
+          // the functions indicated in the !callees metadata.<br class="">
+          Node->addCalledFunction(Call, getOrInsertNodeForCalleesMD(CalleesMD));<br class="">
+        else if (!Callee || !Intrinsic::isLeaf(Callee->getIntrinsicID()))<br class="">
           // Indirect calls of intrinsics are not allowed so no need to check.<br class="">
           // We can be more precise here by using TargetArg returned by<br class="">
           // Intrinsic::isLeaf.<br class="">
@@ -105,6 +115,11 @@ void CallGraph::print(raw_ostream &OS) c<br class="">
<br class="">
   for (CallGraphNode *CN : Nodes)<br class="">
     CN->print(OS);<br class="">
+<br class="">
+  // The iteration order of the DummyNodeMap is deterministic, so we don't need<br class="">
+  // to sort the nodes. Just print them.<br class="">
+  for (auto &Entry : DummyNodeMap)<br class="">
+    Entry.second->print(OS);<br class="">
 }<br class="">
<br class="">
 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)<br class="">
@@ -120,6 +135,12 @@ LLVM_DUMP_METHOD void CallGraph::dump()<br class="">
 Function *CallGraph::removeFunctionFromModule(CallGraphNode *CGN) {<br class="">
   assert(CGN->empty() && "Cannot remove function from call "<br class="">
          "graph if it references other functions!");<br class="">
+<br class="">
+  // If any dummy node references the node for the given function, we first<br class="">
+  // need to remove those edges.<br class="">
+  for (auto &Entry : DummyNodeMap)<br class="">
+    Entry.second->removeAnyCallEdgeTo(CGN);<br class="">
+<br class="">
   Function *F = CGN->getFunction(); // Get the function for the call graph node<br class="">
   FunctionMap.erase(F);             // Remove the call graph node from the map<br class="">
<br class="">
@@ -154,6 +175,21 @@ CallGraphNode *CallGraph::getOrInsertFun<br class="">
   return CGN.get();<br class="">
 }<br class="">
<br class="">
+CallGraphNode *CallGraph::getOrInsertNodeForCalleesMD(MDNode *Callees) {<br class="">
+  auto &CGN = DummyNodeMap[Callees];<br class="">
+  if (CGN)<br class="">
+    return CGN.get();<br class="">
+  CGN = llvm::make_unique<CallGraphNode>(nullptr);<br class="">
+  for (const MDOperand &Op : Callees->operands())<br class="">
+    if (auto *MDConstant = mdconst::extract_or_null<Constant>(Op)) {<br class="">
+      auto *F = cast<Function>(MDConstant);<br class="">
+<br class="">
+      assert(!F->isIntrinsic());<br class="">
+      CGN->addCalledFunction(nullptr, getOrInsertFunction(F));<br class="">
+    }<br class="">
+  return CGN.get();<br class="">
+}<br class="">
+<br class="">
 //===----------------------------------------------------------------------===//<br class="">
 // Implementations of the CallGraphNode class methods.<br class="">
 //<br class="">
@@ -171,7 +207,7 @@ void CallGraphNode::print(raw_ostream &O<br class="">
     if (Function *FI = I.second->getFunction())<br class="">
       OS << "function '" << FI->getName() <<"'\n";<br class="">
     else<br class="">
-      OS << "external node\n";<br class="">
+      OS << "<<null function>><<" << I.second << ">>\n";<br class="">
   }<br class="">
   OS << '\n';<br class="">
 }<br class="">
<br class="">
Modified: llvm/trunk/lib/Analysis/LazyCallGraph.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/LazyCallGraph.cpp?rev=369025&r1=369024&r2=369025&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/LazyCallGraph.cpp?rev=369025&r1=369024&r2=369025&view=diff</a><br class="">
==============================================================================<br class="">
--- llvm/trunk/lib/Analysis/LazyCallGraph.cpp (original)<br class="">
+++ llvm/trunk/lib/Analysis/LazyCallGraph.cpp Thu Aug 15 10:47:53 2019<br class="">
@@ -100,12 +100,14 @@ LazyCallGraph::EdgeSequence &LazyCallGra<br class="">
   for (BasicBlock &BB : *F)<br class="">
     for (Instruction &I : BB) {<br class="">
       if (auto CS = CallSite(&I))<br class="">
-        if (Function *Callee = CS.getCalledFunction())<br class="">
+        for (Function *Callee : CS.getKnownCallees())<br class="">
           if (!Callee->isDeclaration())<br class="">
             if (Callees.insert(Callee).second) {<br class="">
               Visited.insert(Callee);<br class="">
+              auto EdgeK = CS.getCalledFunction() ? LazyCallGraph::Edge::Call<br class="">
+                                                  : LazyCallGraph::Edge::Ref;<br class="">
               addEdge(Edges->Edges, Edges->EdgeIndexMap, G->get(*Callee),<br class="">
-                      LazyCallGraph::Edge::Call);<br class="">
+                      EdgeK);<br class="">
             }<br class="">
<br class="">
       for (Value *Op : I.operand_values())<br class="">
<br class="">
Added: llvm/trunk/test/Analysis/CallGraph/callees-metadata.ll<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/CallGraph/callees-metadata.ll?rev=369025&view=auto" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/CallGraph/callees-metadata.ll?rev=369025&view=auto</a><br class="">
==============================================================================<br class="">
--- llvm/trunk/test/Analysis/CallGraph/callees-metadata.ll (added)<br class="">
+++ llvm/trunk/test/Analysis/CallGraph/callees-metadata.ll Thu Aug 15 10:47:53 2019<br class="">
@@ -0,0 +1,34 @@<br class="">
+; RUN: opt < %s -print-callgraph -disable-output 2>&1 | FileCheck %s<br class="">
+<br class="">
+; CHECK:      Call graph node <<null function>><<{{.+}}>> #uses=0<br class="">
+; CHECK-DAG:    CS<0x0> calls function 'main'<br class="">
+; CHECK-DAG:    CS<0x0> calls function 'add'<br class="">
+; CHECK-DAG:    CS<0x0> calls function 'sub'<br class="">
+;<br class="">
+; CHECK:      Call graph node for function: 'add'<<{{.+}}>> #uses=2<br class="">
+;<br class="">
+; CHECK:      Call graph node for function: 'main'<<{{.+}}>> #uses=1<br class="">
+; CHECK-NEXT:   CS<{{.+}}> calls <<null function>><<[[CALLEES:.+]]>><br class="">
+;<br class="">
+; CHECK:      Call graph node for function: 'sub'<<{{.+}}>> #uses=2<br class="">
+;<br class="">
+; CHECK:      Call graph node <<null function>><<[[CALLEES]]>> #uses=1<br class="">
+; CHECK-DAG:    CS<0x0> calls function 'add'<br class="">
+; CHECK-DAG:    CS<0x0> calls function 'sub'<br class="">
+<br class="">
+define i64 @main(i64 %x, i64 %y, i64 (i64, i64)* %binop) {<br class="">
+  %tmp0 = call i64 %binop(i64 %x, i64 %y), !callees !0<br class="">
+  ret i64 %tmp0<br class="">
+}<br class="">
+<br class="">
+define i64 @add(i64 %x, i64 %y) {<br class="">
+  %tmp0 = add i64 %x, %y<br class="">
+  ret i64 %tmp0<br class="">
+}<br class="">
+<br class="">
+define i64 @sub(i64 %x, i64 %y) {<br class="">
+  %tmp0 = sub i64 %x, %y<br class="">
+  ret i64 %tmp0<br class="">
+}<br class="">
+<br class="">
+!0 = !{i64 (i64, i64)* @add, i64 (i64, i64)* @sub}<br class="">
<br class="">
Modified: llvm/trunk/test/Analysis/CallGraph/non-leaf-intrinsics.ll<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/CallGraph/non-leaf-intrinsics.ll?rev=369025&r1=369024&r2=369025&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/CallGraph/non-leaf-intrinsics.ll?rev=369025&r1=369024&r2=369025&view=diff</a><br class="">
==============================================================================<br class="">
--- llvm/trunk/test/Analysis/CallGraph/non-leaf-intrinsics.ll (original)<br class="">
+++ llvm/trunk/test/Analysis/CallGraph/non-leaf-intrinsics.ll Thu Aug 15 10:47:53 2019<br class="">
@@ -26,7 +26,7 @@ entry:<br class="">
 ; CHECK:  CS<0x0> calls function 'f'<br class="">
<br class="">
 ; CHECK: Call graph node for function: 'calls_patchpoint'<br class="">
-; CHECK-NEXT:  CS<[[addr_1:[^>]+]]> calls external node<br class="">
+; CHECK-NEXT:  CS<[[addr_1:[^>]+]]> calls <<null function>><br class="">
<br class="">
 ; CHECK: Call graph node for function: 'calls_statepoint'<br class="">
-; CHECK-NEXT:  CS<[[addr_0:[^>]+]]> calls external node<br class="">
+; CHECK-NEXT:  CS<[[addr_0:[^>]+]]> calls <<null function>><br class="">
<br class="">
Added: llvm/trunk/test/Analysis/LazyCallGraph/callees-metadata.ll<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/LazyCallGraph/callees-metadata.ll?rev=369025&view=auto" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/LazyCallGraph/callees-metadata.ll?rev=369025&view=auto</a><br class="">
==============================================================================<br class="">
--- llvm/trunk/test/Analysis/LazyCallGraph/callees-metadata.ll (added)<br class="">
+++ llvm/trunk/test/Analysis/LazyCallGraph/callees-metadata.ll Thu Aug 15 10:47:53 2019<br class="">
@@ -0,0 +1,38 @@<br class="">
+; RUN: opt < %s -passes=print-lcg -disable-output 2>&1 | FileCheck %s<br class="">
+<br class="">
+; CHECK:      Edges in function: main<br class="">
+; CHECK-DAG:    ref  -> add<br class="">
+; CHECK-DAG:    ref  -> sub<br class="">
+;<br class="">
+; CHECK:      Edges in function: add<br class="">
+;<br class="">
+; CHECK:      Edges in function: sub<br class="">
+;<br class="">
+; CHECK:      RefSCC with 1 call SCCs:<br class="">
+; CHECK-NEXT:   SCC with 1 functions:<br class="">
+; CHECK-NEXT:     sub<br class="">
+;<br class="">
+; CHECK:      RefSCC with 1 call SCCs:<br class="">
+; CHECK-NEXT:   SCC with 1 functions:<br class="">
+; CHECK-NEXT:     add<br class="">
+;<br class="">
+; CHECK:      RefSCC with 1 call SCCs:<br class="">
+; CHECK-NEXT:   SCC with 1 functions:<br class="">
+; CHECK-NEXT:     main<br class="">
+<br class="">
+define i64 @main(i64 %x, i64 %y, i64 (i64, i64)* %binop) {<br class="">
+  %tmp0 = call i64 %binop(i64 %x, i64 %y), !callees !0<br class="">
+  ret i64 %tmp0<br class="">
+}<br class="">
+<br class="">
+define i64 @add(i64 %x, i64 %y) {<br class="">
+  %tmp0 = add i64 %x, %y<br class="">
+  ret i64 %tmp0<br class="">
+}<br class="">
+<br class="">
+define i64 @sub(i64 %x, i64 %y) {<br class="">
+  %tmp0 = sub i64 %x, %y<br class="">
+  ret i64 %tmp0<br class="">
+}<br class="">
+<br class="">
+!0 = !{i64 (i64, i64)* @add, i64 (i64, i64)* @sub}<br class="">
<br class="">
<br class="">
_______________________________________________<br class="">
llvm-commits mailing list<br class="">
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank" class="">llvm-commits@lists.llvm.org</a><br class="">
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank" class="">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br class="">
</blockquote></div>
<span id="cid:f_jzdybjo50"><t.ii></span></div></blockquote></div><br class=""></div></body></html>