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/ElimAvailExtern.h" 17 #include "llvm/ADT/Statistic.h" 18 #include "llvm/IR/Constants.h" 19 #include "llvm/IR/Module.h" 20 #include "llvm/Transforms/IPO.h" 21 #include "llvm/Transforms/Utils/GlobalStatus.h" 22 #include "llvm/Pass.h" 23 using namespace llvm; 24 25 #define DEBUG_TYPE "elim-avail-extern" 26 27 STATISTIC(NumFunctions, "Number of functions removed"); 28 STATISTIC(NumVariables, "Number of global variables removed"); 29 30 static bool eliminateAvailableExternally(Module &M) { 31 bool Changed = false; 32 33 // Drop initializers of available externally global variables. 34 for (GlobalVariable &GV : M.globals()) { 35 if (!GV.hasAvailableExternallyLinkage()) 36 continue; 37 if (GV.hasInitializer()) { 38 Constant *Init = GV.getInitializer(); 39 GV.setInitializer(nullptr); 40 if (isSafeToDestroyConstant(Init)) 41 Init->destroyConstant(); 42 } 43 GV.removeDeadConstantUsers(); 44 GV.setLinkage(GlobalValue::ExternalLinkage); 45 NumVariables++; 46 Changed = true; 47 } 48 49 // Drop the bodies of available externally functions. 50 for (Function &F : M) { 51 if (!F.hasAvailableExternallyLinkage()) 52 continue; 53 if (!F.isDeclaration()) 54 // This will set the linkage to external 55 F.deleteBody(); 56 F.removeDeadConstantUsers(); 57 NumFunctions++; 58 Changed = true; 59 } 60 61 return Changed; 62 } 63 64 PreservedAnalyses 65 EliminateAvailableExternallyPass::run(Module &M, ModuleAnalysisManager &) { 66 if (!eliminateAvailableExternally(M)) 67 return PreservedAnalyses::all(); 68 return PreservedAnalyses::none(); 69 } 70 71 namespace { 72 struct EliminateAvailableExternallyLegacyPass : public ModulePass { 73 static char ID; // Pass identification, replacement for typeid 74 EliminateAvailableExternallyLegacyPass() : ModulePass(ID) { 75 initializeEliminateAvailableExternallyLegacyPassPass( 76 *PassRegistry::getPassRegistry()); 77 } 78 79 // run - Do the EliminateAvailableExternally pass on the specified module, 80 // optionally updating the specified callgraph to reflect the changes. 81 // 82 bool runOnModule(Module &M) { 83 if (skipModule(M)) 84 return false; 85 return eliminateAvailableExternally(M); 86 } 87 }; 88 } 89 90 char EliminateAvailableExternallyLegacyPass::ID = 0; 91 INITIALIZE_PASS(EliminateAvailableExternallyLegacyPass, "elim-avail-extern", 92 "Eliminate Available Externally Globals", false, false) 93 94 ModulePass *llvm::createEliminateAvailableExternallyPass() { 95 return new EliminateAvailableExternallyLegacyPass(); 96 } 97