1 //===-- ElimAvailExtern.cpp - DCE unreachable internal functions 2 //----------------===// 3 // 4 // The LLVM Compiler Infrastructure 5 // 6 // This file is distributed under the University of Illinois Open Source 7 // License. See LICENSE.TXT for details. 8 // 9 //===----------------------------------------------------------------------===// 10 // 11 // This transform is designed to eliminate available external global 12 // definitions from the program, turning them into declarations. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #include "llvm/Transforms/IPO.h" 17 #include "llvm/ADT/Statistic.h" 18 #include "llvm/IR/Constants.h" 19 #include "llvm/IR/Module.h" 20 #include "llvm/Transforms/Utils/GlobalStatus.h" 21 #include "llvm/Pass.h" 22 using namespace llvm; 23 24 #define DEBUG_TYPE "elim-avail-extern" 25 26 STATISTIC(NumFunctions, "Number of functions removed"); 27 STATISTIC(NumVariables, "Number of global variables removed"); 28 29 namespace { 30 struct EliminateAvailableExternally : public ModulePass { 31 static char ID; // Pass identification, replacement for typeid 32 EliminateAvailableExternally() : ModulePass(ID) { 33 initializeEliminateAvailableExternallyPass( 34 *PassRegistry::getPassRegistry()); 35 } 36 37 // run - Do the EliminateAvailableExternally pass on the specified module, 38 // optionally updating the specified callgraph to reflect the changes. 39 // 40 bool runOnModule(Module &M) override; 41 }; 42 } 43 44 char EliminateAvailableExternally::ID = 0; 45 INITIALIZE_PASS(EliminateAvailableExternally, "elim-avail-extern", 46 "Eliminate Available Externally Globals", false, false) 47 48 ModulePass *llvm::createEliminateAvailableExternallyPass() { 49 return new EliminateAvailableExternally(); 50 } 51 52 static void convertAliasToDeclaration(GlobalAlias &GA, Module &M) { 53 GlobalValue *GVal = GA.getBaseObject(); 54 GlobalValue *NewGV; 55 if (auto *GVar = dyn_cast<GlobalVariable>(GVal)) { 56 GlobalVariable *NewGVar = new GlobalVariable( 57 M, GVar->getType()->getElementType(), GVar->isConstant(), 58 GVar->getLinkage(), /*init*/ nullptr, GA.getName(), GVar, 59 GVar->getThreadLocalMode(), GVar->getType()->getAddressSpace()); 60 NewGV = NewGVar; 61 NewGV->copyAttributesFrom(GVar); 62 } else { 63 auto *F = dyn_cast<Function>(GVal); 64 assert(F); 65 Function *NewF = Function::Create(F->getFunctionType(), F->getLinkage(), 66 GA.getName(), &M); 67 NewGV = NewF; 68 NewGV->copyAttributesFrom(F); 69 } 70 GA.replaceAllUsesWith(ConstantExpr::getBitCast(NewGV, GA.getType())); 71 GA.eraseFromParent(); 72 } 73 74 bool EliminateAvailableExternally::runOnModule(Module &M) { 75 bool Changed = false; 76 77 // Convert any aliases that alias with an available externally 78 // value (which will be turned into declarations later on in this routine) 79 // into declarations themselves. All aliases must be definitions, and 80 // must alias with a definition. So this involves creating a declaration 81 // equivalent to the alias's base object. 82 for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E;) { 83 // Increment the iterator first since we may delete the current alias. 84 GlobalAlias &GA = *(I++); 85 GlobalValue *GVal = GA.getBaseObject(); 86 if (!GVal->hasAvailableExternallyLinkage()) 87 continue; 88 convertAliasToDeclaration(GA, M); 89 Changed = true; 90 } 91 92 // Drop initializers of available externally global variables. 93 for (GlobalVariable &GV : M.globals()) { 94 if (!GV.hasAvailableExternallyLinkage()) 95 continue; 96 if (GV.hasInitializer()) { 97 Constant *Init = GV.getInitializer(); 98 GV.setInitializer(nullptr); 99 if (isSafeToDestroyConstant(Init)) 100 Init->destroyConstant(); 101 } 102 GV.removeDeadConstantUsers(); 103 GV.setLinkage(GlobalValue::ExternalLinkage); 104 NumVariables++; 105 Changed = true; 106 } 107 108 // Drop the bodies of available externally functions. 109 for (Function &F : M) { 110 if (!F.hasAvailableExternallyLinkage()) 111 continue; 112 if (!F.isDeclaration()) 113 // This will set the linkage to external 114 F.deleteBody(); 115 F.removeDeadConstantUsers(); 116 NumFunctions++; 117 Changed = true; 118 } 119 120 return Changed; 121 } 122