106f32e7eSjoerg //===- ElimAvailExtern.cpp - DCE unreachable internal functions -----------===//
206f32e7eSjoerg //
306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606f32e7eSjoerg //
706f32e7eSjoerg //===----------------------------------------------------------------------===//
806f32e7eSjoerg //
906f32e7eSjoerg // This transform is designed to eliminate available external global
1006f32e7eSjoerg // definitions from the program, turning them into declarations.
1106f32e7eSjoerg //
1206f32e7eSjoerg //===----------------------------------------------------------------------===//
1306f32e7eSjoerg 
1406f32e7eSjoerg #include "llvm/Transforms/IPO/ElimAvailExtern.h"
1506f32e7eSjoerg #include "llvm/ADT/Statistic.h"
1606f32e7eSjoerg #include "llvm/IR/Constant.h"
1706f32e7eSjoerg #include "llvm/IR/Function.h"
1806f32e7eSjoerg #include "llvm/IR/GlobalValue.h"
1906f32e7eSjoerg #include "llvm/IR/GlobalVariable.h"
2006f32e7eSjoerg #include "llvm/IR/Module.h"
21*da58b97aSjoerg #include "llvm/InitializePasses.h"
2206f32e7eSjoerg #include "llvm/Pass.h"
2306f32e7eSjoerg #include "llvm/Transforms/IPO.h"
2406f32e7eSjoerg #include "llvm/Transforms/Utils/GlobalStatus.h"
2506f32e7eSjoerg 
2606f32e7eSjoerg using namespace llvm;
2706f32e7eSjoerg 
2806f32e7eSjoerg #define DEBUG_TYPE "elim-avail-extern"
2906f32e7eSjoerg 
3006f32e7eSjoerg STATISTIC(NumFunctions, "Number of functions removed");
3106f32e7eSjoerg STATISTIC(NumVariables, "Number of global variables removed");
3206f32e7eSjoerg 
eliminateAvailableExternally(Module & M)3306f32e7eSjoerg static bool eliminateAvailableExternally(Module &M) {
3406f32e7eSjoerg   bool Changed = false;
3506f32e7eSjoerg 
3606f32e7eSjoerg   // Drop initializers of available externally global variables.
3706f32e7eSjoerg   for (GlobalVariable &GV : M.globals()) {
3806f32e7eSjoerg     if (!GV.hasAvailableExternallyLinkage())
3906f32e7eSjoerg       continue;
4006f32e7eSjoerg     if (GV.hasInitializer()) {
4106f32e7eSjoerg       Constant *Init = GV.getInitializer();
4206f32e7eSjoerg       GV.setInitializer(nullptr);
4306f32e7eSjoerg       if (isSafeToDestroyConstant(Init))
4406f32e7eSjoerg         Init->destroyConstant();
4506f32e7eSjoerg     }
4606f32e7eSjoerg     GV.removeDeadConstantUsers();
4706f32e7eSjoerg     GV.setLinkage(GlobalValue::ExternalLinkage);
4806f32e7eSjoerg     NumVariables++;
4906f32e7eSjoerg     Changed = true;
5006f32e7eSjoerg   }
5106f32e7eSjoerg 
5206f32e7eSjoerg   // Drop the bodies of available externally functions.
5306f32e7eSjoerg   for (Function &F : M) {
5406f32e7eSjoerg     if (!F.hasAvailableExternallyLinkage())
5506f32e7eSjoerg       continue;
5606f32e7eSjoerg     if (!F.isDeclaration())
5706f32e7eSjoerg       // This will set the linkage to external
5806f32e7eSjoerg       F.deleteBody();
5906f32e7eSjoerg     F.removeDeadConstantUsers();
6006f32e7eSjoerg     NumFunctions++;
6106f32e7eSjoerg     Changed = true;
6206f32e7eSjoerg   }
6306f32e7eSjoerg 
6406f32e7eSjoerg   return Changed;
6506f32e7eSjoerg }
6606f32e7eSjoerg 
6706f32e7eSjoerg PreservedAnalyses
run(Module & M,ModuleAnalysisManager &)6806f32e7eSjoerg EliminateAvailableExternallyPass::run(Module &M, ModuleAnalysisManager &) {
6906f32e7eSjoerg   if (!eliminateAvailableExternally(M))
7006f32e7eSjoerg     return PreservedAnalyses::all();
7106f32e7eSjoerg   return PreservedAnalyses::none();
7206f32e7eSjoerg }
7306f32e7eSjoerg 
7406f32e7eSjoerg namespace {
7506f32e7eSjoerg 
7606f32e7eSjoerg struct EliminateAvailableExternallyLegacyPass : public ModulePass {
7706f32e7eSjoerg   static char ID; // Pass identification, replacement for typeid
7806f32e7eSjoerg 
EliminateAvailableExternallyLegacyPass__anon49199e500111::EliminateAvailableExternallyLegacyPass7906f32e7eSjoerg   EliminateAvailableExternallyLegacyPass() : ModulePass(ID) {
8006f32e7eSjoerg     initializeEliminateAvailableExternallyLegacyPassPass(
8106f32e7eSjoerg         *PassRegistry::getPassRegistry());
8206f32e7eSjoerg   }
8306f32e7eSjoerg 
8406f32e7eSjoerg   // run - Do the EliminateAvailableExternally pass on the specified module,
8506f32e7eSjoerg   // optionally updating the specified callgraph to reflect the changes.
runOnModule__anon49199e500111::EliminateAvailableExternallyLegacyPass8606f32e7eSjoerg   bool runOnModule(Module &M) override {
8706f32e7eSjoerg     if (skipModule(M))
8806f32e7eSjoerg       return false;
8906f32e7eSjoerg     return eliminateAvailableExternally(M);
9006f32e7eSjoerg   }
9106f32e7eSjoerg };
9206f32e7eSjoerg 
9306f32e7eSjoerg } // end anonymous namespace
9406f32e7eSjoerg 
9506f32e7eSjoerg char EliminateAvailableExternallyLegacyPass::ID = 0;
9606f32e7eSjoerg 
9706f32e7eSjoerg INITIALIZE_PASS(EliminateAvailableExternallyLegacyPass, "elim-avail-extern",
9806f32e7eSjoerg                 "Eliminate Available Externally Globals", false, false)
9906f32e7eSjoerg 
createEliminateAvailableExternallyPass()10006f32e7eSjoerg ModulePass *llvm::createEliminateAvailableExternallyPass() {
10106f32e7eSjoerg   return new EliminateAvailableExternallyLegacyPass();
10206f32e7eSjoerg }
103