33#define DEBUG_TYPE "globaldce"
42 bool runOnModule(
Module &M)
override {
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())
84 return !RI->getReturnValue();
92void GlobalDCEPass::ComputeDependencies(
Value *V,
95 Function *Parent =
I->getParent()->getParent();
101 auto [Where,
Inserted] = ConstantDependenciesCache.try_emplace(CE);
102 SmallPtrSetImpl<GlobalValue *> &LocalDeps = Where->second;
104 for (User *CEUser :
CE->users())
105 ComputeDependencies(CEUser, LocalDeps);
111void GlobalDCEPass::UpdateGVDependencies(
GlobalValue &GV) {
112 SmallPtrSet<GlobalValue *, 8> Deps;
113 for (User *User : GV.
users())
114 ComputeDependencies(User, Deps);
116 for (GlobalValue *GVU : Deps) {
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) {
151 for (GlobalVariable &GV :
M.globals()) {
160 for (MDNode *
Type : Types) {
180 VFESafeVTables.insert(&GV);
187 uint64_t CallOffset) {
188 for (
const auto &VTableInfo : TypeIdMap[TypeId]) {
189 GlobalVariable *
VTable = VTableInfo.first;
190 uint64_t VTableOffset = VTableInfo.second;
194 *
Caller->getParent(), VTable);
197 VFESafeVTables.erase(VTable);
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()) {
231 Value *TypeIdValue = CI->getArgOperand(2);
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) {
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)
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)
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...
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.
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.
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.
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.