Index: llvm/include/llvm/IR/Function.h =================================================================== --- llvm/include/llvm/IR/Function.h +++ llvm/include/llvm/IR/Function.h @@ -877,7 +877,8 @@ /// 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 Index: llvm/lib/Analysis/CallGraph.cpp =================================================================== --- llvm/lib/Analysis/CallGraph.cpp +++ llvm/lib/Analysis/CallGraph.cpp @@ -81,7 +81,8 @@ // 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); Index: llvm/lib/IR/Function.cpp =================================================================== --- llvm/lib/IR/Function.cpp +++ llvm/lib/IR/Function.cpp @@ -1582,7 +1582,8 @@ /// uses. bool Function::hasAddressTaken(const User **PutOffender, bool IgnoreCallbackUses, - bool IgnoreAssumeLikeCalls) const { + bool IgnoreAssumeLikeCalls, + bool IngoreLLVMUsed) const { for (const Use &U : uses()) { const User *FU = U.getUser(); if (isa(FU)) @@ -1607,6 +1608,17 @@ continue; } } + if (IngoreLLVMUsed && FU->hasOneUse() && + !FU->user_begin()->user_empty() && + llvm::all_of(FU->user_begin()->users(), [](const User *U) { + if (const auto *GV = dyn_cast(U)) + return GV->hasName() && + (GV->getName().equals("llvm.compiler.used") || + GV->getName().equals("llvm.used")); + return false; + })) { + continue; + } if (PutOffender) *PutOffender = FU; return true; Index: llvm/test/Analysis/CallGraph/ignore-llvm-used.ll =================================================================== --- /dev/null +++ llvm/test/Analysis/CallGraph/ignore-llvm-used.ll @@ -0,0 +1,22 @@ +; RUN: opt < %s -print-callgraph -disable-output 2>&1 | FileCheck %s +; CHECK: Call graph node <><<{{.*}}>> #uses=0 +; CHECK-NEXT: CS calls function 'bar' +; CHECK-EMPTY: +; CHECK-NEXT: Call graph node for function: 'bar'<<{{.*}}>> #uses=1 +; CHECK-EMPTY: +; CHECK-NEXT: Call graph node for function: 'foo'<<{{.*}}>> #uses=0 +; CHECK-EMPTY: + +@llvm.used = appending global [1 x i8*] [i8* bitcast (void ()* @foo to i8*)] +@llvm.compiler.used = appending global [1 x i8*] [i8* bitcast (void ()* @foo to i8*)] +@array = appending global [1 x i8*] [i8* bitcast (void ()* @bar to i8*)] + +define internal void @foo() { +entry: + ret void +} + +define internal void @bar() { +entry: + ret void +}