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