[llvm] d9c9904 - Option to ignore llvm[.compiler].used uses in hasAddressTaken()

Stanislav Mekhanoshin via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 25 10:06:37 PST 2021


Author: Stanislav Mekhanoshin
Date: 2021-02-25T10:06:24-08:00
New Revision: d9c99043bdde5637bf32edaad10d1b8f8cd10b38

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

LOG: Option to ignore llvm[.compiler].used uses in hasAddressTaken()

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

Added: 
    llvm/test/Analysis/CallGraph/ignore-llvm-used.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 187da2a09027..b1ef3b113190 100644
--- a/llvm/include/llvm/IR/Function.h
+++ b/llvm/include/llvm/IR/Function.h
@@ -873,11 +873,13 @@ 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,
-  /// ignores callback uses, and assume like pointer annotation calls.
+  /// ignores callback uses, assume like pointer annotation calls, and
+  /// references in llvm.used and llvm.compiler.used variables.
   ///
   bool hasAddressTaken(const User ** = nullptr,
                        bool IgnoreCallbackUses = false,
-                       bool IgnoreAssumeLikeCalls = false) const;
+                       bool IgnoreAssumeLikeCalls = false,
+                       bool IngoreLLVMUsed = 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 014f3eb4abc9..bca45678c6a2 100644
--- a/llvm/lib/Analysis/CallGraph.cpp
+++ b/llvm/lib/Analysis/CallGraph.cpp
@@ -81,7 +81,8 @@ void CallGraph::addToCallGraph(Function *F) {
   // it is not a callback, then anything could call it.
   if (!F->hasLocalLinkage() ||
       F->hasAddressTaken(nullptr, /*IgnoreCallbackUses=*/true,
-                         /* IgnoreAssumeLikeCalls */ true))
+                         /* IgnoreAssumeLikeCalls */ true,
+                         /* IgnoreLLVMUsed */ true))
     ExternalCallingNode->addCalledFunction(nullptr, Node);
 
   populateCallGraphNode(Node);

diff  --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp
index c6932f0ec446..0396fdaba73f 100644
--- a/llvm/lib/IR/Function.cpp
+++ b/llvm/lib/IR/Function.cpp
@@ -52,6 +52,7 @@
 #include "llvm/IR/MDBuilder.h"
 #include "llvm/IR/Metadata.h"
 #include "llvm/IR/Module.h"
+#include "llvm/IR/Operator.h"
 #include "llvm/IR/SymbolTableListTraits.h"
 #include "llvm/IR/Type.h"
 #include "llvm/IR/Use.h"
@@ -1579,10 +1580,12 @@ 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. Optionally ignores callback
-/// uses and assume like pointer annotation calls.
+/// uses, assume like pointer annotation calls, and references in llvm.used
+/// and llvm.compiler.used variables.
 bool Function::hasAddressTaken(const User **PutOffender,
                                bool IgnoreCallbackUses,
-                               bool IgnoreAssumeLikeCalls) const {
+                               bool IgnoreAssumeLikeCalls,
+                               bool IgnoreLLVMUsed) const {
   for (const Use &U : uses()) {
     const User *FU = U.getUser();
     if (isa<BlockAddress>(FU))
@@ -1607,6 +1610,20 @@ bool Function::hasAddressTaken(const User **PutOffender,
             continue;
         }
       }
+      if (IgnoreLLVMUsed && !FU->user_empty()) {
+        const User *FUU = FU;
+        if (isa<BitCastOperator>(FU) && FU->hasOneUse() &&
+            !FU->user_begin()->user_empty())
+          FUU = *FU->user_begin();
+        if (llvm::all_of(FUU->users(), [](const User *U) {
+              if (const auto *GV = dyn_cast<GlobalVariable>(U))
+                return GV->hasName() &&
+                       (GV->getName().equals("llvm.compiler.used") ||
+                        GV->getName().equals("llvm.used"));
+              return false;
+            }))
+          continue;
+      }
       if (PutOffender)
         *PutOffender = FU;
       return true;

diff  --git a/llvm/test/Analysis/CallGraph/ignore-llvm-used.ll b/llvm/test/Analysis/CallGraph/ignore-llvm-used.ll
new file mode 100644
index 000000000000..ac6569b96f06
--- /dev/null
+++ b/llvm/test/Analysis/CallGraph/ignore-llvm-used.ll
@@ -0,0 +1,29 @@
+; RUN: opt < %s -print-callgraph -disable-output 2>&1 | FileCheck %s
+; CHECK: Call graph node <<null function>><<{{.*}}>>  #uses=0
+; CHECK-NEXT:  CS<None> calls function 'unused'
+; CHECK-EMPTY:
+; CHECK-NEXT:   Call graph node for function: 'unused'<<{{.*}}>>  #uses=1
+; CHECK-EMPTY:
+; CHECK-NEXT:   Call graph node for function: 'used1'<<{{.*}}>>  #uses=0
+; CHECK-EMPTY:
+; CHECK-NEXT:   Call graph node for function: 'used2'<<{{.*}}>>  #uses=0
+; CHECK-EMPTY:
+
+ at llvm.used = appending global [1 x i8*] [i8* bitcast (void ()* @used1 to i8*)]
+ at llvm.compiler.used = appending global [1 x void()*] [void ()* @used2]
+ at array = appending global [1 x i8*] [i8* bitcast (void ()* @unused to i8*)]
+
+define internal void @used1() {
+entry:
+  ret void
+}
+
+define internal void @used2() {
+entry:
+  ret void
+}
+
+define internal void @unused() {
+entry:
+  ret void
+}


        


More information about the llvm-commits mailing list