Home | History | Annotate | Download | only in IPO
      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