1e9ea08a0SEugene Zelenko //===- ElimAvailExtern.cpp - DCE unreachable internal functions -----------===//
2d3a33a16STeresa Johnson //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6d3a33a16STeresa Johnson //
7d3a33a16STeresa Johnson //===----------------------------------------------------------------------===//
8d3a33a16STeresa Johnson //
9d3a33a16STeresa Johnson // This transform is designed to eliminate available external global
10d3a33a16STeresa Johnson // definitions from the program, turning them into declarations.
11d3a33a16STeresa Johnson //
12d3a33a16STeresa Johnson //===----------------------------------------------------------------------===//
13d3a33a16STeresa Johnson
14344e838fSDavide Italiano #include "llvm/Transforms/IPO/ElimAvailExtern.h"
15d3a33a16STeresa Johnson #include "llvm/ADT/Statistic.h"
16e9ea08a0SEugene Zelenko #include "llvm/IR/Constant.h"
17e9ea08a0SEugene Zelenko #include "llvm/IR/Function.h"
18e9ea08a0SEugene Zelenko #include "llvm/IR/GlobalValue.h"
19e9ea08a0SEugene Zelenko #include "llvm/IR/GlobalVariable.h"
20d3a33a16STeresa Johnson #include "llvm/IR/Module.h"
21*05da2fe5SReid Kleckner #include "llvm/InitializePasses.h"
226bda14b3SChandler Carruth #include "llvm/Pass.h"
23344e838fSDavide Italiano #include "llvm/Transforms/IPO.h"
24d3a33a16STeresa Johnson #include "llvm/Transforms/Utils/GlobalStatus.h"
25e9ea08a0SEugene Zelenko
26d3a33a16STeresa Johnson using namespace llvm;
27d3a33a16STeresa Johnson
28d3a33a16STeresa Johnson #define DEBUG_TYPE "elim-avail-extern"
29d3a33a16STeresa Johnson
30d3a33a16STeresa Johnson STATISTIC(NumFunctions, "Number of functions removed");
31d3a33a16STeresa Johnson STATISTIC(NumVariables, "Number of global variables removed");
32d3a33a16STeresa Johnson
eliminateAvailableExternally(Module & M)33344e838fSDavide Italiano static bool eliminateAvailableExternally(Module &M) {
34d3a33a16STeresa Johnson bool Changed = false;
35d3a33a16STeresa Johnson
36d3a33a16STeresa Johnson // Drop initializers of available externally global variables.
37771e3196SYaron Keren for (GlobalVariable &GV : M.globals()) {
38771e3196SYaron Keren if (!GV.hasAvailableExternallyLinkage())
39d3a33a16STeresa Johnson continue;
40771e3196SYaron Keren if (GV.hasInitializer()) {
41771e3196SYaron Keren Constant *Init = GV.getInitializer();
42771e3196SYaron Keren GV.setInitializer(nullptr);
43d3a33a16STeresa Johnson if (isSafeToDestroyConstant(Init))
44d3a33a16STeresa Johnson Init->destroyConstant();
45d3a33a16STeresa Johnson }
46771e3196SYaron Keren GV.removeDeadConstantUsers();
47771e3196SYaron Keren GV.setLinkage(GlobalValue::ExternalLinkage);
48d3a33a16STeresa Johnson NumVariables++;
49c7ed52f2STeresa Johnson Changed = true;
50d3a33a16STeresa Johnson }
51d3a33a16STeresa Johnson
52d3a33a16STeresa Johnson // Drop the bodies of available externally functions.
53771e3196SYaron Keren for (Function &F : M) {
54771e3196SYaron Keren if (!F.hasAvailableExternallyLinkage())
55d3a33a16STeresa Johnson continue;
56771e3196SYaron Keren if (!F.isDeclaration())
57d3a33a16STeresa Johnson // This will set the linkage to external
58771e3196SYaron Keren F.deleteBody();
59771e3196SYaron Keren F.removeDeadConstantUsers();
60d3a33a16STeresa Johnson NumFunctions++;
61c7ed52f2STeresa Johnson Changed = true;
62d3a33a16STeresa Johnson }
63d3a33a16STeresa Johnson
64d3a33a16STeresa Johnson return Changed;
65d3a33a16STeresa Johnson }
66344e838fSDavide Italiano
67164a2aa6SChandler Carruth PreservedAnalyses
run(Module & M,ModuleAnalysisManager &)68164a2aa6SChandler Carruth EliminateAvailableExternallyPass::run(Module &M, ModuleAnalysisManager &) {
69344e838fSDavide Italiano if (!eliminateAvailableExternally(M))
70344e838fSDavide Italiano return PreservedAnalyses::all();
71344e838fSDavide Italiano return PreservedAnalyses::none();
72344e838fSDavide Italiano }
73344e838fSDavide Italiano
74344e838fSDavide Italiano namespace {
75e9ea08a0SEugene Zelenko
76344e838fSDavide Italiano struct EliminateAvailableExternallyLegacyPass : public ModulePass {
77344e838fSDavide Italiano static char ID; // Pass identification, replacement for typeid
78e9ea08a0SEugene Zelenko
EliminateAvailableExternallyLegacyPass__anon806e13df0111::EliminateAvailableExternallyLegacyPass79344e838fSDavide Italiano EliminateAvailableExternallyLegacyPass() : ModulePass(ID) {
80344e838fSDavide Italiano initializeEliminateAvailableExternallyLegacyPassPass(
81344e838fSDavide Italiano *PassRegistry::getPassRegistry());
82344e838fSDavide Italiano }
83344e838fSDavide Italiano
84344e838fSDavide Italiano // run - Do the EliminateAvailableExternally pass on the specified module,
85344e838fSDavide Italiano // optionally updating the specified callgraph to reflect the changes.
runOnModule__anon806e13df0111::EliminateAvailableExternallyLegacyPass86e9ea08a0SEugene Zelenko bool runOnModule(Module &M) override {
87344e838fSDavide Italiano if (skipModule(M))
88344e838fSDavide Italiano return false;
89344e838fSDavide Italiano return eliminateAvailableExternally(M);
90344e838fSDavide Italiano }
91344e838fSDavide Italiano };
92e9ea08a0SEugene Zelenko
93e9ea08a0SEugene Zelenko } // end anonymous namespace
94344e838fSDavide Italiano
95344e838fSDavide Italiano char EliminateAvailableExternallyLegacyPass::ID = 0;
96e9ea08a0SEugene Zelenko
97344e838fSDavide Italiano INITIALIZE_PASS(EliminateAvailableExternallyLegacyPass, "elim-avail-extern",
98344e838fSDavide Italiano "Eliminate Available Externally Globals", false, false)
99344e838fSDavide Italiano
createEliminateAvailableExternallyPass()100344e838fSDavide Italiano ModulePass *llvm::createEliminateAvailableExternallyPass() {
101344e838fSDavide Italiano return new EliminateAvailableExternallyLegacyPass();
102344e838fSDavide Italiano }
103