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.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 bool EliminateAvailableExternally::runOnModule(Module &M) {
     53   bool Changed = false;
     54 
     55   // Drop initializers of available externally global variables.
     56   for (GlobalVariable &GV : M.globals()) {
     57     if (!GV.hasAvailableExternallyLinkage())
     58       continue;
     59     if (GV.hasInitializer()) {
     60       Constant *Init = GV.getInitializer();
     61       GV.setInitializer(nullptr);
     62       if (isSafeToDestroyConstant(Init))
     63         Init->destroyConstant();
     64     }
     65     GV.removeDeadConstantUsers();
     66     GV.setLinkage(GlobalValue::ExternalLinkage);
     67     NumVariables++;
     68     Changed = true;
     69   }
     70 
     71   // Drop the bodies of available externally functions.
     72   for (Function &F : M) {
     73     if (!F.hasAvailableExternallyLinkage())
     74       continue;
     75     if (!F.isDeclaration())
     76       // This will set the linkage to external
     77       F.deleteBody();
     78     F.removeDeadConstantUsers();
     79     NumFunctions++;
     80     Changed = true;
     81   }
     82 
     83   return Changed;
     84 }
     85