33#define DEBUG_TYPE "globaldce"
40 bool runOnModule(
Module &M)
override {
46 auto PA = Impl.run(M,
MAM);
47 return !PA.areAllPreserved();
55char GlobalDCELegacyPass::ID = 0;
64 cl::desc(
"Enable virtual function elimination"));
66STATISTIC(NumAliases ,
"Number of global aliases removed");
67STATISTIC(NumFunctions,
"Number of functions removed");
68STATISTIC(NumIFuncs,
"Number of indirect functions removed");
69STATISTIC(NumVariables,
"Number of global variables removed");
70STATISTIC(NumVFuncs,
"Number of virtual functions removed");
75 if (
F->isDeclaration())
78 for (
auto &
I : Entry) {
79 if (
I.isDebugOrPseudoInst())
82 return !RI->getReturnValue();
90void GlobalDCEPass::ComputeDependencies(
Value *V,
93 Function *Parent =
I->getParent()->getParent();
99 auto [Where,
Inserted] = ConstantDependenciesCache.try_emplace(CE);
100 SmallPtrSetImpl<GlobalValue *> &LocalDeps = Where->second;
102 for (User *CEUser :
CE->users())
103 ComputeDependencies(CEUser, LocalDeps);
109void GlobalDCEPass::UpdateGVDependencies(
GlobalValue &GV) {
110 SmallPtrSet<GlobalValue *, 8> Deps;
111 for (User *User : GV.
users())
112 ComputeDependencies(User, Deps);
114 for (GlobalValue *GVU : Deps) {
124 GVDependencies[GVU].insert(&GV);
131 auto const Ret = AliveGlobals.insert(&GV);
138 for (
auto &&CM :
make_range(ComdatMembers.equal_range(
C))) {
139 MarkLive(*CM.second, Updates);
145void GlobalDCEPass::ScanVTables(
Module &M) {
149 for (GlobalVariable &GV :
M.globals()) {
158 for (MDNode *
Type : Types) {
177 VFESafeVTables.insert(&GV);
183 uint64_t CallOffset) {
184 for (
const auto &VTableInfo : TypeIdMap[TypeId]) {
185 GlobalVariable *
VTable = VTableInfo.first;
186 uint64_t VTableOffset = VTableInfo.second;
190 *
Caller->getParent(), VTable);
193 VFESafeVTables.erase(VTable);
200 VFESafeVTables.erase(VTable);
205 <<
Callee->getName() <<
"\n");
206 GVDependencies[
Caller].insert(Callee);
210void GlobalDCEPass::ScanTypeCheckedLoadIntrinsics(
Module &M) {
215 &M, Intrinsic::type_checked_load_relative);
217 auto scan = [&](
Function *CheckedLoadFunc) {
218 if (!CheckedLoadFunc)
221 for (
auto *U : CheckedLoadFunc->users()) {
227 Value *TypeIdValue = CI->getArgOperand(2);
231 ScanVTableLoad(CI->getFunction(), TypeId,
Offset->getZExtValue());
235 for (
const auto &VTableInfo : TypeIdMap[TypeId]) {
236 VFESafeVTables.erase(VTableInfo.first);
242 scan(TypeCheckedLoadFunc);
243 scan(TypeCheckedLoadRelativeFunc);
246void GlobalDCEPass::AddVirtualFunctionDependencies(
Module &M) {
255 M.getModuleFlag(
"Virtual Function Elim"));
256 if (!Val || Val->isZero())
261 if (VFESafeVTables.empty())
264 ScanTypeCheckedLoadIntrinsics(M);
267 dbgs() <<
"VFE safe vtables:\n";
268 for (
auto *VTable : VFESafeVTables)
291 ComdatMembers.insert(std::make_pair(
C, &
F));
294 ComdatMembers.insert(std::make_pair(
C, &GV));
296 if (
Comdat *
C = GA.getComdat())
297 ComdatMembers.insert(std::make_pair(
C, &GA));
301 AddVirtualFunctionDependencies(M);
305 GO.removeDeadConstantUsers();
309 if (!GO.isDeclaration())
310 if (!GO.isDiscardableIfUnused())
313 UpdateGVDependencies(GO);
318 GA.removeDeadConstantUsers();
320 if (!GA.isDiscardableIfUnused())
323 UpdateGVDependencies(GA);
328 GIF.removeDeadConstantUsers();
330 if (!GIF.isDiscardableIfUnused())
333 UpdateGVDependencies(GIF);
340 while (!NewLiveGVs.
empty()) {
342 for (
auto *GVD : GVDependencies[LGV])
343 MarkLive(*GVD, &NewLiveGVs);
351 std::vector<GlobalVariable *> DeadGlobalVars;
353 if (!AliveGlobals.count(&GV)) {
354 DeadGlobalVars.push_back(&GV);
355 if (GV.hasInitializer()) {
357 GV.setInitializer(
nullptr);
359 Init->destroyConstant();
364 std::vector<Function *> DeadFunctions;
366 if (!AliveGlobals.count(&
F)) {
367 DeadFunctions.push_back(&
F);
368 if (!
F.isDeclaration())
373 std::vector<GlobalAlias*> DeadAliases;
375 if (!AliveGlobals.count(&GA)) {
376 DeadAliases.push_back(&GA);
377 GA.setAliasee(
nullptr);
381 std::vector<GlobalIFunc*> DeadIFuncs;
383 if (!AliveGlobals.count(&GIF)) {
384 DeadIFuncs.push_back(&GIF);
385 GIF.setResolver(
nullptr);
390 auto EraseUnusedGlobalValue = [&](
GlobalValue *GV) {
396 NumFunctions += DeadFunctions.size();
398 if (!
F->use_empty()) {
416 EraseUnusedGlobalValue(
F);
419 NumVariables += DeadGlobalVars.size();
421 EraseUnusedGlobalValue(GV);
423 NumAliases += DeadAliases.size();
425 EraseUnusedGlobalValue(GA);
427 NumIFuncs += DeadIFuncs.size();
429 EraseUnusedGlobalValue(GIF);
432 AliveGlobals.clear();
433 ConstantDependenciesCache.clear();
434 GVDependencies.clear();
435 ComdatMembers.clear();
437 VFESafeVTables.clear();
447 OS, MapClassName2PassName);
449 OS <<
"<vfe-linkage-unit-visibility>";
static bool isEmptyFunction(Function *F)
Returns true if F is effectively empty.
static cl::opt< bool > ClEnableVFE("enable-vfe", cl::Hidden, cl::init(true), cl::desc("Enable virtual function elimination"))
Module.h This file contains the declarations for the Module class.
ModuleAnalysisManager MAM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file defines the SmallPtrSet class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
LLVM Basic Block Representation.
static LLVM_ABI ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
This is an important base class in LLVM.
const Constant * stripPointerCasts() const
LLVM_ABI void removeDeadConstantUsers() const
If there are any dead constant users dangling off of this constant, remove them.
Pass to remove unused function declarations.
LLVM_ABI void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &)
@ VCallVisibilityLinkageUnit
@ VCallVisibilityTranslationUnit
LLVM_ABI bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
LLVM_ABI const Comdat * getComdat() const
LLVM_ABI void eraseFromParent()
This method unlinks 'this' from the containing module and deletes it.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
A Module instance is used to store all the information related to an LLVM module.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
bool erase(PtrType Ptr)
Remove pointer from the set.
void insert_range(Range &&R)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
LLVM Value Representation.
iterator_range< user_iterator > users()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
MDNode * getMetadata(unsigned KindID) const
Get the current metadata attachments for the given kind, if any.
An efficient, type-erasing, non-owning reference to a callable.
This class implements an extremely fast bulk output stream that can only output to a stream.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
LLVM_ABI Function * getDeclarationIfExists(const Module *M, ID id)
Look up the Function declaration of the intrinsic id in the Module M and return it if it exists.
@ CE
Windows NT (Windows on ARM)
initializer< Ty > init(const Ty &Val)
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > dyn_extract_or_null(Y &&MD)
Extract a Value from Metadata, if any, allowing null.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
LLVM_ABI ModulePass * createGlobalDCEPass()
bool isSafeToDestroyConstant(const Constant *C)
It is safe to destroy a constant iff it is only used by constants itself.
bool optimizeGlobalCtorsList(Module &M, function_ref< bool(uint32_t, Function *)> ShouldRemove)
Call "ShouldRemove" for every entry in M's global_ctor list and remove the entries for which it retur...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
void replaceRelativePointerUsersWithZero(Constant *C)
Finds the same "relative pointer" pattern as described above, where the target is C,...
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Constant * getPointerAtOffset(Constant *I, uint64_t Offset, Module &M, Constant *TopLevelGlobal=nullptr)
Processes a Constant recursively looking into elements of arrays, structs and expressions to find a t...
A CRTP mix-in to automatically provide informational APIs needed for passes.