blob: fc52db562c623341516b248ad8f8342704b6532a [file] [log] [blame]
Eugene Zelenkoe9ea08a2017-10-10 22:49:55 +00001//===- ElimAvailExtern.cpp - DCE unreachable internal functions -----------===//
Teresa Johnsond3a33a12015-07-06 16:22:42 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Teresa Johnsond3a33a12015-07-06 16:22:42 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This transform is designed to eliminate available external global
10// definitions from the program, turning them into declarations.
11//
12//===----------------------------------------------------------------------===//
13
Davide Italiano344e8382016-05-05 02:37:32 +000014#include "llvm/Transforms/IPO/ElimAvailExtern.h"
Teresa Johnsond3a33a12015-07-06 16:22:42 +000015#include "llvm/ADT/Statistic.h"
Eugene Zelenkoe9ea08a2017-10-10 22:49:55 +000016#include "llvm/IR/Constant.h"
17#include "llvm/IR/Function.h"
18#include "llvm/IR/GlobalValue.h"
19#include "llvm/IR/GlobalVariable.h"
Teresa Johnsond3a33a12015-07-06 16:22:42 +000020#include "llvm/IR/Module.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000021#include "llvm/Pass.h"
Davide Italiano344e8382016-05-05 02:37:32 +000022#include "llvm/Transforms/IPO.h"
Teresa Johnsond3a33a12015-07-06 16:22:42 +000023#include "llvm/Transforms/Utils/GlobalStatus.h"
Eugene Zelenkoe9ea08a2017-10-10 22:49:55 +000024
Teresa Johnsond3a33a12015-07-06 16:22:42 +000025using namespace llvm;
26
27#define DEBUG_TYPE "elim-avail-extern"
28
Teresa Johnsond3a33a12015-07-06 16:22:42 +000029STATISTIC(NumFunctions, "Number of functions removed");
30STATISTIC(NumVariables, "Number of global variables removed");
31
Davide Italiano344e8382016-05-05 02:37:32 +000032static bool eliminateAvailableExternally(Module &M) {
Teresa Johnsond3a33a12015-07-06 16:22:42 +000033 bool Changed = false;
34
35 // Drop initializers of available externally global variables.
Teresa Johnsonf72278f2015-11-02 18:02:11 +000036 for (GlobalVariable &GV : M.globals()) {
Yaron Keren771e3192015-09-04 20:24:24 +000037 if (!GV.hasAvailableExternallyLinkage())
Teresa Johnsond3a33a12015-07-06 16:22:42 +000038 continue;
Yaron Keren771e3192015-09-04 20:24:24 +000039 if (GV.hasInitializer()) {
40 Constant *Init = GV.getInitializer();
41 GV.setInitializer(nullptr);
Teresa Johnsond3a33a12015-07-06 16:22:42 +000042 if (isSafeToDestroyConstant(Init))
43 Init->destroyConstant();
44 }
Yaron Keren771e3192015-09-04 20:24:24 +000045 GV.removeDeadConstantUsers();
46 GV.setLinkage(GlobalValue::ExternalLinkage);
Teresa Johnsond3a33a12015-07-06 16:22:42 +000047 NumVariables++;
Teresa Johnsonc7ed52f2015-11-03 00:14:15 +000048 Changed = true;
Teresa Johnsond3a33a12015-07-06 16:22:42 +000049 }
50
51 // Drop the bodies of available externally functions.
Yaron Keren771e3192015-09-04 20:24:24 +000052 for (Function &F : M) {
53 if (!F.hasAvailableExternallyLinkage())
Teresa Johnsond3a33a12015-07-06 16:22:42 +000054 continue;
Yaron Keren771e3192015-09-04 20:24:24 +000055 if (!F.isDeclaration())
Teresa Johnsond3a33a12015-07-06 16:22:42 +000056 // This will set the linkage to external
Yaron Keren771e3192015-09-04 20:24:24 +000057 F.deleteBody();
58 F.removeDeadConstantUsers();
Teresa Johnsond3a33a12015-07-06 16:22:42 +000059 NumFunctions++;
Teresa Johnsonc7ed52f2015-11-03 00:14:15 +000060 Changed = true;
Teresa Johnsond3a33a12015-07-06 16:22:42 +000061 }
62
Teresa Johnsond3a33a12015-07-06 16:22:42 +000063 return Changed;
64}
Davide Italiano344e8382016-05-05 02:37:32 +000065
Chandler Carruth164a2aa62016-06-17 00:11:01 +000066PreservedAnalyses
67EliminateAvailableExternallyPass::run(Module &M, ModuleAnalysisManager &) {
Davide Italiano344e8382016-05-05 02:37:32 +000068 if (!eliminateAvailableExternally(M))
69 return PreservedAnalyses::all();
70 return PreservedAnalyses::none();
71}
72
73namespace {
Eugene Zelenkoe9ea08a2017-10-10 22:49:55 +000074
Davide Italiano344e8382016-05-05 02:37:32 +000075struct EliminateAvailableExternallyLegacyPass : public ModulePass {
76 static char ID; // Pass identification, replacement for typeid
Eugene Zelenkoe9ea08a2017-10-10 22:49:55 +000077
Davide Italiano344e8382016-05-05 02:37:32 +000078 EliminateAvailableExternallyLegacyPass() : ModulePass(ID) {
79 initializeEliminateAvailableExternallyLegacyPassPass(
80 *PassRegistry::getPassRegistry());
81 }
82
83 // run - Do the EliminateAvailableExternally pass on the specified module,
84 // optionally updating the specified callgraph to reflect the changes.
Eugene Zelenkoe9ea08a2017-10-10 22:49:55 +000085 bool runOnModule(Module &M) override {
Davide Italiano344e8382016-05-05 02:37:32 +000086 if (skipModule(M))
87 return false;
88 return eliminateAvailableExternally(M);
89 }
90};
Eugene Zelenkoe9ea08a2017-10-10 22:49:55 +000091
92} // end anonymous namespace
Davide Italiano344e8382016-05-05 02:37:32 +000093
94char EliminateAvailableExternallyLegacyPass::ID = 0;
Eugene Zelenkoe9ea08a2017-10-10 22:49:55 +000095
Davide Italiano344e8382016-05-05 02:37:32 +000096INITIALIZE_PASS(EliminateAvailableExternallyLegacyPass, "elim-avail-extern",
97 "Eliminate Available Externally Globals", false, false)
98
99ModulePass *llvm::createEliminateAvailableExternallyPass() {
100 return new EliminateAvailableExternallyLegacyPass();
101}