[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