33#define DEBUG_TYPE "globaldce"
48 auto PA = Impl.run(M,
MAM);
49 return !PA.areAllPreserved();
57char GlobalDCELegacyPass::ID = 0;
66 cl::desc(
"Enable virtual function elimination"));
68STATISTIC(NumAliases ,
"Number of global aliases removed");
69STATISTIC(NumFunctions,
"Number of functions removed");
70STATISTIC(NumIFuncs,
"Number of indirect functions removed");
71STATISTIC(NumVariables,
"Number of global variables removed");
72STATISTIC(NumVFuncs,
"Number of virtual functions removed");
77 if (
F->isDeclaration())
80 for (
auto &
I : Entry) {
81 if (
I.isDebugOrPseudoInst())
83 if (
auto *RI = dyn_cast<ReturnInst>(&
I))
84 return !RI->getReturnValue();
92void GlobalDCEPass::ComputeDependencies(
Value *V,
94 if (
auto *
I = dyn_cast<Instruction>(V)) {
95 Function *Parent =
I->getParent()->getParent();
97 }
else if (
auto *GV = dyn_cast<GlobalValue>(V)) {
99 }
else if (
auto *CE = dyn_cast<Constant>(V)) {
101 auto [Where,
Inserted] = ConstantDependenciesCache.try_emplace(CE);
104 for (
User *CEUser :
CE->users())
105 ComputeDependencies(CEUser, LocalDeps);
111void GlobalDCEPass::UpdateGVDependencies(
GlobalValue &GV) {
114 ComputeDependencies(
User, Deps);
121 if (VFESafeVTables.count(GVU) && isa<Function>(&GV)) {
126 GVDependencies[GVU].insert(&GV);
133 auto const Ret = AliveGlobals.insert(&GV);
140 for (
auto &&CM :
make_range(ComdatMembers.equal_range(
C))) {
141 MarkLive(*CM.second, Updates);
147void GlobalDCEPass::ScanVTables(
Module &M) {
165 cast<ConstantAsMetadata>(
Type->getOperand(0))->getValue())
174 if (
auto GO = dyn_cast<GlobalObject>(&GV)) {
180 VFESafeVTables.insert(&GV);
188 for (
const auto &VTableInfo : TypeIdMap[TypeId]) {
190 uint64_t VTableOffset = VTableInfo.second;
194 *
Caller->getParent(), VTable);
197 VFESafeVTables.erase(VTable);
201 auto Callee = dyn_cast<Function>(
Ptr->stripPointerCasts());
204 VFESafeVTables.erase(VTable);
209 <<
Callee->getName() <<
"\n");
210 GVDependencies[
Caller].insert(Callee);
214void GlobalDCEPass::ScanTypeCheckedLoadIntrinsics(
Module &M) {
219 &M, Intrinsic::type_checked_load_relative);
221 auto scan = [&](
Function *CheckedLoadFunc) {
222 if (!CheckedLoadFunc)
225 for (
auto *U : CheckedLoadFunc->users()) {
226 auto CI = dyn_cast<CallInst>(U);
230 auto *
Offset = dyn_cast<ConstantInt>(CI->getArgOperand(1));
231 Value *TypeIdValue = CI->getArgOperand(2);
232 auto *TypeId = cast<MetadataAsValue>(TypeIdValue)->
getMetadata();
235 ScanVTableLoad(CI->getFunction(), TypeId,
Offset->getZExtValue());
239 for (
const auto &VTableInfo : TypeIdMap[TypeId]) {
240 VFESafeVTables.erase(VTableInfo.first);
246 scan(TypeCheckedLoadFunc);
247 scan(TypeCheckedLoadRelativeFunc);
250void GlobalDCEPass::AddVirtualFunctionDependencies(
Module &M) {
258 auto *Val = mdconst::dyn_extract_or_null<ConstantInt>(
259 M.getModuleFlag(
"Virtual Function Elim"));
260 if (!Val || Val->isZero())
265 if (VFESafeVTables.empty())
268 ScanTypeCheckedLoadIntrinsics(M);
271 dbgs() <<
"VFE safe vtables:\n";
272 for (
auto *VTable : VFESafeVTables)
278 bool Changed =
false;
295 ComdatMembers.insert(std::make_pair(
C, &
F));
298 ComdatMembers.insert(std::make_pair(
C, &GV));
300 if (
Comdat *
C = GA.getComdat())
301 ComdatMembers.insert(std::make_pair(
C, &GA));
305 AddVirtualFunctionDependencies(M);
309 GO.removeDeadConstantUsers();
313 if (!GO.isDeclaration())
314 if (!GO.isDiscardableIfUnused())
317 UpdateGVDependencies(GO);
322 GA.removeDeadConstantUsers();
324 if (!GA.isDiscardableIfUnused())
327 UpdateGVDependencies(GA);
332 GIF.removeDeadConstantUsers();
334 if (!GIF.isDiscardableIfUnused())
337 UpdateGVDependencies(GIF);
344 while (!NewLiveGVs.empty()) {
346 for (
auto *GVD : GVDependencies[LGV])
347 MarkLive(*GVD, &NewLiveGVs);
355 std::vector<GlobalVariable *> DeadGlobalVars;
357 if (!AliveGlobals.count(&GV)) {
358 DeadGlobalVars.push_back(&GV);
359 if (GV.hasInitializer()) {
361 GV.setInitializer(
nullptr);
363 Init->destroyConstant();
368 std::vector<Function *> DeadFunctions;
370 if (!AliveGlobals.count(&
F)) {
371 DeadFunctions.push_back(&
F);
372 if (!
F.isDeclaration())
377 std::vector<GlobalAlias*> DeadAliases;
379 if (!AliveGlobals.count(&GA)) {
380 DeadAliases.push_back(&GA);
381 GA.setAliasee(
nullptr);
385 std::vector<GlobalIFunc*> DeadIFuncs;
387 if (!AliveGlobals.count(&GIF)) {
388 DeadIFuncs.push_back(&GIF);
389 GIF.setResolver(
nullptr);
394 auto EraseUnusedGlobalValue = [&](
GlobalValue *GV) {
400 NumFunctions += DeadFunctions.size();
402 if (!
F->use_empty()) {
420 EraseUnusedGlobalValue(
F);
423 NumVariables += DeadGlobalVars.size();
425 EraseUnusedGlobalValue(GV);
427 NumAliases += DeadAliases.size();
429 EraseUnusedGlobalValue(GA);
431 NumIFuncs += DeadIFuncs.size();
433 EraseUnusedGlobalValue(GIF);
436 AliveGlobals.clear();
437 ConstantDependenciesCache.clear();
438 GVDependencies.clear();
439 ComdatMembers.clear();
441 VFESafeVTables.clear();
451 OS, MapClassName2PassName);
453 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)
A container for analyses that lazily runs them and caches their results.
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.
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...
bool skipModule(const Module &M) const
Optional passes call this function to check whether the pass should be skipped.
virtual bool runOnModule(Module &M)=0
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
A Module instance is used to store all the information related to an LLVM module.
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
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.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
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.
The instances of the Type class are immutable: once they are created, they are never changed.
TypeID
Definitions of all of the base types for the Type system.
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)
This is an optimization pass for GlobalISel generic memory operations.
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.
LLVM_ABI void initializeGlobalDCELegacyPassPass(PassRegistry &)
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.
void replaceRelativePointerUsersWithZero(Constant *C)
Finds the same "relative pointer" pattern as described above, where the target is C,...
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.