[llvm] 205dc09 - [CallGraph] Ignore callback uses

Giorgis Georgakoudis via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 9 13:18:56 PDT 2020


Author: Giorgis Georgakoudis
Date: 2020-07-09T13:13:46-07:00
New Revision: 205dc0922d5f7305226f7457fcbcb4224c92530c

URL: https://github.com/llvm/llvm-project/commit/205dc0922d5f7305226f7457fcbcb4224c92530c
DIFF: https://github.com/llvm/llvm-project/commit/205dc0922d5f7305226f7457fcbcb4224c92530c.diff

LOG: [CallGraph] Ignore callback uses

Summary:
Ignore callback uses when adding a callback function
in the CallGraph. Callback functions are typically
created when outlining, e.g. for OpenMP, so they have
internal scope and linkage. They should not be added
to the ExternalCallingNode since they are only callable
by the specified caller function at creation time.

A CGSCC pass, such as OpenMPOpt, may need to update
the CallGraph by adding a new outlined callback function.
Without ignoring callback uses, adding breaks CGSCC
pass restrictions and results to a broken CallGraph.

Reviewers: jdoerfert

Subscribers: hiraditya, sstefan1, llvm-commits

Tags: #llvm

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

Added: 
    llvm/test/Analysis/CallGraph/ignore-callback-uses.ll

Modified: 
    llvm/include/llvm/IR/Function.h
    llvm/lib/Analysis/CallGraph.cpp
    llvm/lib/IR/Function.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/IR/Function.h b/llvm/include/llvm/IR/Function.h
index ee66abc3eaed..bb4ec13c7610 100644
--- a/llvm/include/llvm/IR/Function.h
+++ b/llvm/include/llvm/IR/Function.h
@@ -830,9 +830,11 @@ class Function : public GlobalObject, public ilist_node<Function> {
 
   /// hasAddressTaken - returns true if there are any uses of this function
   /// other than direct calls or invokes to it, or blockaddress expressions.
-  /// Optionally passes back an offending user for diagnostic purposes.
+  /// Optionally passes back an offending user for diagnostic purposes and
+  /// ignores callback uses.
   ///
-  bool hasAddressTaken(const User** = nullptr) const;
+  bool hasAddressTaken(const User ** = nullptr,
+                       bool IgnoreCallbackUses = false) const;
 
   /// isDefTriviallyDead - Return true if it is trivially safe to remove
   /// this function definition from the module (because it isn't externally

diff  --git a/llvm/lib/Analysis/CallGraph.cpp b/llvm/lib/Analysis/CallGraph.cpp
index d8abccfdb095..08264512f400 100644
--- a/llvm/lib/Analysis/CallGraph.cpp
+++ b/llvm/lib/Analysis/CallGraph.cpp
@@ -77,9 +77,11 @@ bool CallGraph::invalidate(Module &, const PreservedAnalyses &PA,
 void CallGraph::addToCallGraph(Function *F) {
   CallGraphNode *Node = getOrInsertFunction(F);
 
-  // If this function has external linkage or has its address taken, anything
-  // could call it.
-  if (!F->hasLocalLinkage() || F->hasAddressTaken())
+  bool IgnoreCallbackUses = true;
+
+  // If this function has external linkage or has its address taken and
+  // it is not a callback, then anything could call it.
+  if (!F->hasLocalLinkage() || F->hasAddressTaken(nullptr, IgnoreCallbackUses))
     ExternalCallingNode->addCalledFunction(nullptr, Node);
 
   populateCallGraphNode(Node);

diff  --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp
index 0ec0cce83a8c..995bc40c362f 100644
--- a/llvm/lib/IR/Function.cpp
+++ b/llvm/lib/IR/Function.cpp
@@ -20,6 +20,7 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/IR/AbstractCallSite.h"
 #include "llvm/IR/Argument.h"
 #include "llvm/IR/Attributes.h"
 #include "llvm/IR/BasicBlock.h"
@@ -1484,12 +1485,18 @@ Optional<Function *> Intrinsic::remangleIntrinsicFunction(Function *F) {
 }
 
 /// hasAddressTaken - returns true if there are any uses of this function
-/// other than direct calls or invokes to it.
-bool Function::hasAddressTaken(const User* *PutOffender) const {
+/// other than direct calls or invokes to it. Optionally ignores callback
+/// uses.
+bool Function::hasAddressTaken(const User **PutOffender,
+                               bool IgnoreCallbackUses) const {
   for (const Use &U : uses()) {
     const User *FU = U.getUser();
     if (isa<BlockAddress>(FU))
       continue;
+
+    if (IgnoreCallbackUses && AbstractCallSite(&U))
+      continue;
+
     const auto *Call = dyn_cast<CallBase>(FU);
     if (!Call) {
       if (PutOffender)

diff  --git a/llvm/test/Analysis/CallGraph/ignore-callback-uses.ll b/llvm/test/Analysis/CallGraph/ignore-callback-uses.ll
new file mode 100644
index 000000000000..8964ca1efd86
--- /dev/null
+++ b/llvm/test/Analysis/CallGraph/ignore-callback-uses.ll
@@ -0,0 +1,51 @@
+; RUN: opt < %s -print-callgraph -disable-output 2>&1 | FileCheck %s
+; CHECK: Call graph node <<null function>><<{{.*}}>>  #uses=0
+; CHECK-NEXT:   CS<{{.*}}> calls function 'f'
+; CHECK-NEXT:   CS<{{.*}}> calls function '__kmpc_fork_call'
+; CHECK-EMPTY:
+
+%struct.ident_t = type { i32, i32, i32, i32, i8* }
+
+ at 0 = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00", align 1
+ at 1 = private unnamed_addr global %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* @0, i32 0, i32 0) }, align 8
+
+; Function Attrs: noinline nounwind optnone uwtable
+define dso_local void @f() {
+entry:
+  br label %omp_parallel
+
+omp_parallel:                                     ; preds = %entry
+  call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @1, i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @f..omp_par to void (i32*, i32*, ...)*))
+  br label %omp.par.exit.split
+
+omp.par.exit.split:                               ; preds = %omp_parallel
+  ret void
+}
+
+; Function Attrs: norecurse nounwind
+define internal void @f..omp_par(i32* noalias %tid.addr, i32* noalias %zero.addr) {
+omp.par.entry:
+  %tid.addr.local = alloca i32, align 4
+  %0 = load i32, i32* %tid.addr, align 4
+  store i32 %0, i32* %tid.addr.local, align 4
+  %tid = load i32, i32* %tid.addr.local, align 4
+  br label %omp.par.region
+
+omp.par.exit.split.exitStub:                      ; preds = %omp.par.outlined.exit
+  ret void
+
+omp.par.region:                                   ; preds = %omp.par.entry
+  br label %omp.par.pre_finalize
+
+omp.par.pre_finalize:                             ; preds = %omp.par.region
+  br label %omp.par.outlined.exit
+
+omp.par.outlined.exit:                            ; preds = %omp.par.pre_finalize
+  br label %omp.par.exit.split.exitStub
+}
+
+; Function Attrs: nounwind
+declare !callback !2 void @__kmpc_fork_call(%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) #2
+
+!2 = !{!3}
+!3 = !{i64 2, i64 -1, i64 -1, i1 true}


        


More information about the llvm-commits mailing list