1*9880d681SAndroid Build Coastguard Worker //===-- ElimAvailExtern.cpp - DCE unreachable internal functions
2*9880d681SAndroid Build Coastguard Worker //----------------===//
3*9880d681SAndroid Build Coastguard Worker //
4*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
5*9880d681SAndroid Build Coastguard Worker //
6*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
7*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
8*9880d681SAndroid Build Coastguard Worker //
9*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
10*9880d681SAndroid Build Coastguard Worker //
11*9880d681SAndroid Build Coastguard Worker // This transform is designed to eliminate available external global
12*9880d681SAndroid Build Coastguard Worker // definitions from the program, turning them into declarations.
13*9880d681SAndroid Build Coastguard Worker //
14*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
15*9880d681SAndroid Build Coastguard Worker
16*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/IPO/ElimAvailExtern.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Statistic.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Constants.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Module.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/IPO.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Utils/GlobalStatus.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/Pass.h"
23*9880d681SAndroid Build Coastguard Worker using namespace llvm;
24*9880d681SAndroid Build Coastguard Worker
25*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "elim-avail-extern"
26*9880d681SAndroid Build Coastguard Worker
27*9880d681SAndroid Build Coastguard Worker STATISTIC(NumFunctions, "Number of functions removed");
28*9880d681SAndroid Build Coastguard Worker STATISTIC(NumVariables, "Number of global variables removed");
29*9880d681SAndroid Build Coastguard Worker
eliminateAvailableExternally(Module & M)30*9880d681SAndroid Build Coastguard Worker static bool eliminateAvailableExternally(Module &M) {
31*9880d681SAndroid Build Coastguard Worker bool Changed = false;
32*9880d681SAndroid Build Coastguard Worker
33*9880d681SAndroid Build Coastguard Worker // Drop initializers of available externally global variables.
34*9880d681SAndroid Build Coastguard Worker for (GlobalVariable &GV : M.globals()) {
35*9880d681SAndroid Build Coastguard Worker if (!GV.hasAvailableExternallyLinkage())
36*9880d681SAndroid Build Coastguard Worker continue;
37*9880d681SAndroid Build Coastguard Worker if (GV.hasInitializer()) {
38*9880d681SAndroid Build Coastguard Worker Constant *Init = GV.getInitializer();
39*9880d681SAndroid Build Coastguard Worker GV.setInitializer(nullptr);
40*9880d681SAndroid Build Coastguard Worker if (isSafeToDestroyConstant(Init))
41*9880d681SAndroid Build Coastguard Worker Init->destroyConstant();
42*9880d681SAndroid Build Coastguard Worker }
43*9880d681SAndroid Build Coastguard Worker GV.removeDeadConstantUsers();
44*9880d681SAndroid Build Coastguard Worker GV.setLinkage(GlobalValue::ExternalLinkage);
45*9880d681SAndroid Build Coastguard Worker NumVariables++;
46*9880d681SAndroid Build Coastguard Worker Changed = true;
47*9880d681SAndroid Build Coastguard Worker }
48*9880d681SAndroid Build Coastguard Worker
49*9880d681SAndroid Build Coastguard Worker // Drop the bodies of available externally functions.
50*9880d681SAndroid Build Coastguard Worker for (Function &F : M) {
51*9880d681SAndroid Build Coastguard Worker if (!F.hasAvailableExternallyLinkage())
52*9880d681SAndroid Build Coastguard Worker continue;
53*9880d681SAndroid Build Coastguard Worker if (!F.isDeclaration())
54*9880d681SAndroid Build Coastguard Worker // This will set the linkage to external
55*9880d681SAndroid Build Coastguard Worker F.deleteBody();
56*9880d681SAndroid Build Coastguard Worker F.removeDeadConstantUsers();
57*9880d681SAndroid Build Coastguard Worker NumFunctions++;
58*9880d681SAndroid Build Coastguard Worker Changed = true;
59*9880d681SAndroid Build Coastguard Worker }
60*9880d681SAndroid Build Coastguard Worker
61*9880d681SAndroid Build Coastguard Worker return Changed;
62*9880d681SAndroid Build Coastguard Worker }
63*9880d681SAndroid Build Coastguard Worker
64*9880d681SAndroid Build Coastguard Worker PreservedAnalyses
run(Module & M,ModuleAnalysisManager &)65*9880d681SAndroid Build Coastguard Worker EliminateAvailableExternallyPass::run(Module &M, ModuleAnalysisManager &) {
66*9880d681SAndroid Build Coastguard Worker if (!eliminateAvailableExternally(M))
67*9880d681SAndroid Build Coastguard Worker return PreservedAnalyses::all();
68*9880d681SAndroid Build Coastguard Worker return PreservedAnalyses::none();
69*9880d681SAndroid Build Coastguard Worker }
70*9880d681SAndroid Build Coastguard Worker
71*9880d681SAndroid Build Coastguard Worker namespace {
72*9880d681SAndroid Build Coastguard Worker struct EliminateAvailableExternallyLegacyPass : public ModulePass {
73*9880d681SAndroid Build Coastguard Worker static char ID; // Pass identification, replacement for typeid
EliminateAvailableExternallyLegacyPass__anona39f45470111::EliminateAvailableExternallyLegacyPass74*9880d681SAndroid Build Coastguard Worker EliminateAvailableExternallyLegacyPass() : ModulePass(ID) {
75*9880d681SAndroid Build Coastguard Worker initializeEliminateAvailableExternallyLegacyPassPass(
76*9880d681SAndroid Build Coastguard Worker *PassRegistry::getPassRegistry());
77*9880d681SAndroid Build Coastguard Worker }
78*9880d681SAndroid Build Coastguard Worker
79*9880d681SAndroid Build Coastguard Worker // run - Do the EliminateAvailableExternally pass on the specified module,
80*9880d681SAndroid Build Coastguard Worker // optionally updating the specified callgraph to reflect the changes.
81*9880d681SAndroid Build Coastguard Worker //
runOnModule__anona39f45470111::EliminateAvailableExternallyLegacyPass82*9880d681SAndroid Build Coastguard Worker bool runOnModule(Module &M) {
83*9880d681SAndroid Build Coastguard Worker if (skipModule(M))
84*9880d681SAndroid Build Coastguard Worker return false;
85*9880d681SAndroid Build Coastguard Worker return eliminateAvailableExternally(M);
86*9880d681SAndroid Build Coastguard Worker }
87*9880d681SAndroid Build Coastguard Worker };
88*9880d681SAndroid Build Coastguard Worker }
89*9880d681SAndroid Build Coastguard Worker
90*9880d681SAndroid Build Coastguard Worker char EliminateAvailableExternallyLegacyPass::ID = 0;
91*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS(EliminateAvailableExternallyLegacyPass, "elim-avail-extern",
92*9880d681SAndroid Build Coastguard Worker "Eliminate Available Externally Globals", false, false)
93*9880d681SAndroid Build Coastguard Worker
createEliminateAvailableExternallyPass()94*9880d681SAndroid Build Coastguard Worker ModulePass *llvm::createEliminateAvailableExternallyPass() {
95*9880d681SAndroid Build Coastguard Worker return new EliminateAvailableExternallyLegacyPass();
96*9880d681SAndroid Build Coastguard Worker }
97