blob: 7f138d206faca25bc3c27ca98774292706cd37e8 [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"
Reid Kleckner05da2fe2019-11-13 13:15:01 -080021#include "llvm/InitializePasses.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000022#include "llvm/Pass.h"
Davide Italiano344e8382016-05-05 02:37:32 +000023#include "llvm/Transforms/IPO.h"
Teresa Johnsond3a33a12015-07-06 16:22:42 +000024#include "llvm/Transforms/Utils/GlobalStatus.h"
Eugene Zelenkoe9ea08a2017-10-10 22:49:55 +000025
Teresa Johnsond3a33a12015-07-06 16:22:42 +000026using namespace llvm;
27
28#define DEBUG_TYPE "elim-avail-extern"
29
Teresa Johnsond3a33a12015-07-06 16:22:42 +000030STATISTIC(NumFunctions, "Number of functions removed");
31STATISTIC(NumVariables, "Number of global variables removed");
32
Davide Italiano344e8382016-05-05 02:37:32 +000033static bool eliminateAvailableExternally(Module &M) {
Teresa Johnsond3a33a12015-07-06 16:22:42 +000034 bool Changed = false;
35
36 // Drop initializers of available externally global variables.
Teresa Johnsonf72278f2015-11-02 18:02:11 +000037 for (GlobalVariable &GV : M.globals()) {
Yaron Keren771e3192015-09-04 20:24:24 +000038 if (!GV.hasAvailableExternallyLinkage())
Teresa Johnsond3a33a12015-07-06 16:22:42 +000039 continue;
Yaron Keren771e3192015-09-04 20:24:24 +000040 if (GV.hasInitializer()) {
41 Constant *Init = GV.getInitializer();
42 GV.setInitializer(nullptr);
Teresa Johnsond3a33a12015-07-06 16:22:42 +000043 if (isSafeToDestroyConstant(Init))
44 Init->destroyConstant();
45 }
Yaron Keren771e3192015-09-04 20:24:24 +000046 GV.removeDeadConstantUsers();
47 GV.setLinkage(GlobalValue::ExternalLinkage);
Teresa Johnsond3a33a12015-07-06 16:22:42 +000048 NumVariables++;
Teresa Johnsonc7ed52f2015-11-03 00:14:15 +000049 Changed = true;
Teresa Johnsond3a33a12015-07-06 16:22:42 +000050 }
51
52 // Drop the bodies of available externally functions.
Yaron Keren771e3192015-09-04 20:24:24 +000053 for (Function &F : M) {
54 if (!F.hasAvailableExternallyLinkage())
Teresa Johnsond3a33a12015-07-06 16:22:42 +000055 continue;
Yaron Keren771e3192015-09-04 20:24:24 +000056 if (!F.isDeclaration())
Teresa Johnsond3a33a12015-07-06 16:22:42 +000057 // This will set the linkage to external
Yaron Keren771e3192015-09-04 20:24:24 +000058 F.deleteBody();
59 F.removeDeadConstantUsers();
Teresa Johnsond3a33a12015-07-06 16:22:42 +000060 NumFunctions++;
Teresa Johnsonc7ed52f2015-11-03 00:14:15 +000061 Changed = true;
Teresa Johnsond3a33a12015-07-06 16:22:42 +000062 }
63
Teresa Johnsond3a33a12015-07-06 16:22:42 +000064 return Changed;
65}
Davide Italiano344e8382016-05-05 02:37:32 +000066
Chandler Carruth164a2aa62016-06-17 00:11:01 +000067PreservedAnalyses
68EliminateAvailableExternallyPass::run(Module &M, ModuleAnalysisManager &) {
Davide Italiano344e8382016-05-05 02:37:32 +000069 if (!eliminateAvailableExternally(M))
70 return PreservedAnalyses::all();
71 return PreservedAnalyses::none();
72}
73
74namespace {
Eugene Zelenkoe9ea08a2017-10-10 22:49:55 +000075
Davide Italiano344e8382016-05-05 02:37:32 +000076struct EliminateAvailableExternallyLegacyPass : public ModulePass {
77 static char ID; // Pass identification, replacement for typeid
Eugene Zelenkoe9ea08a2017-10-10 22:49:55 +000078
Davide Italiano344e8382016-05-05 02:37:32 +000079 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.
Eugene Zelenkoe9ea08a2017-10-10 22:49:55 +000086 bool runOnModule(Module &M) override {
Davide Italiano344e8382016-05-05 02:37:32 +000087 if (skipModule(M))
88 return false;
89 return eliminateAvailableExternally(M);
90 }
91};
Eugene Zelenkoe9ea08a2017-10-10 22:49:55 +000092
93} // end anonymous namespace
Davide Italiano344e8382016-05-05 02:37:32 +000094
95char EliminateAvailableExternallyLegacyPass::ID = 0;
Eugene Zelenkoe9ea08a2017-10-10 22:49:55 +000096
Davide Italiano344e8382016-05-05 02:37:32 +000097INITIALIZE_PASS(EliminateAvailableExternallyLegacyPass, "elim-avail-extern",
98 "Eliminate Available Externally Globals", false, false)
99
100ModulePass *llvm::createEliminateAvailableExternallyPass() {
101 return new EliminateAvailableExternallyLegacyPass();
102}