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) {
178 VFESafeVTables.insert(&GV);
185 uint64_t CallOffset) {
186 for (
const auto &VTableInfo : TypeIdMap[TypeId]) {
187 GlobalVariable *
VTable = VTableInfo.first;
188 uint64_t VTableOffset = VTableInfo.second;
192 *
Caller->getParent(), VTable);
195 VFESafeVTables.erase(VTable);
202 VFESafeVTables.erase(VTable);
207 <<
Callee->getName() <<
"\n");
208 GVDependencies[
Caller].insert(Callee);
212void GlobalDCEPass::ScanTypeCheckedLoadIntrinsics(
Module &M) {
217 &M, Intrinsic::type_checked_load_relative);
219 auto scan = [&](
Function *CheckedLoadFunc) {
220 if (!CheckedLoadFunc)
223 for (
auto *U : CheckedLoadFunc->users()) {
229 Value *TypeIdValue = CI->getArgOperand(2);
233 ScanVTableLoad(CI->getFunction(), TypeId,
Offset->getZExtValue());
237 for (
const auto &VTableInfo : TypeIdMap[TypeId]) {
238 VFESafeVTables.erase(VTableInfo.first);
244 scan(TypeCheckedLoadFunc);
245 scan(TypeCheckedLoadRelativeFunc);
248void GlobalDCEPass::AddVirtualFunctionDependencies(
Module &M) {
257 M.getModuleFlag(
"Virtual Function Elim"));
258 if (!Val || Val->isZero())
263 if (VFESafeVTables.empty())
266 ScanTypeCheckedLoadIntrinsics(M);
269 dbgs() <<
"VFE safe vtables:\n";
270 for (
auto *VTable : VFESafeVTables)
293 ComdatMembers.insert(std::make_pair(
C, &
F));
296 ComdatMembers.insert(std::make_pair(
C, &GV));
298 if (
Comdat *
C = GA.getComdat())
299 ComdatMembers.insert(std::make_pair(
C, &GA));
303 AddVirtualFunctionDependencies(M);
307 GO.removeDeadConstantUsers();
311 if (!GO.isDeclaration())
312 if (!GO.isDiscardableIfUnused())
315 UpdateGVDependencies(GO);
320 GA.removeDeadConstantUsers();
322 if (!GA.isDiscardableIfUnused())
325 UpdateGVDependencies(GA);
330 GIF.removeDeadConstantUsers();
332 if (!GIF.isDiscardableIfUnused())
335 UpdateGVDependencies(GIF);
342 while (!NewLiveGVs.
empty()) {
344 for (
auto *GVD : GVDependencies[LGV])
345 MarkLive(*GVD, &NewLiveGVs);
353 std::vector<GlobalVariable *> DeadGlobalVars;
355 if (!AliveGlobals.count(&GV)) {
356 DeadGlobalVars.push_back(&GV);
357 if (GV.hasInitializer()) {
359 GV.setInitializer(
nullptr);
361 Init->destroyConstant();
366 std::vector<Function *> DeadFunctions;
368 if (!AliveGlobals.count(&
F)) {
369 DeadFunctions.push_back(&
F);
370 if (!
F.isDeclaration())
375 std::vector<GlobalAlias*> DeadAliases;
377 if (!AliveGlobals.count(&GA)) {
378 DeadAliases.push_back(&GA);
379 GA.setAliasee(
nullptr);
383 std::vector<GlobalIFunc*> DeadIFuncs;
385 if (!AliveGlobals.count(&GIF)) {
386 DeadIFuncs.push_back(&GIF);
387 GIF.setResolver(
nullptr);
392 auto EraseUnusedGlobalValue = [&](
GlobalValue *GV) {
398 NumFunctions += DeadFunctions.size();
400 if (!
F->use_empty()) {
418 EraseUnusedGlobalValue(
F);
421 NumVariables += DeadGlobalVars.size();
423 EraseUnusedGlobalValue(GV);
425 NumAliases += DeadAliases.size();
427 EraseUnusedGlobalValue(GA);
429 NumIFuncs += DeadIFuncs.size();
431 EraseUnusedGlobalValue(GIF);
434 AliveGlobals.clear();
435 ConstantDependenciesCache.clear();
436 GVDependencies.clear();
437 ComdatMembers.clear();
439 VFESafeVTables.clear();
449 OS, MapClassName2PassName);
451 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.