ElimAvailExtern.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  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. #include "llvm/Transforms/IPO/ElimAvailExtern.h"
  14. #include "llvm/ADT/Statistic.h"
  15. #include "llvm/IR/Constant.h"
  16. #include "llvm/IR/Function.h"
  17. #include "llvm/IR/GlobalValue.h"
  18. #include "llvm/IR/GlobalVariable.h"
  19. #include "llvm/IR/Module.h"
  20. #include "llvm/InitializePasses.h"
  21. #include "llvm/Pass.h"
  22. #include "llvm/Transforms/IPO.h"
  23. #include "llvm/Transforms/Utils/GlobalStatus.h"
  24. using namespace llvm;
  25. #define DEBUG_TYPE "elim-avail-extern"
  26. STATISTIC(NumFunctions, "Number of functions removed");
  27. STATISTIC(NumVariables, "Number of global variables removed");
  28. static bool eliminateAvailableExternally(Module &M) {
  29. bool Changed = false;
  30. // Drop initializers of available externally global variables.
  31. for (GlobalVariable &GV : M.globals()) {
  32. if (!GV.hasAvailableExternallyLinkage())
  33. continue;
  34. if (GV.hasInitializer()) {
  35. Constant *Init = GV.getInitializer();
  36. GV.setInitializer(nullptr);
  37. if (isSafeToDestroyConstant(Init))
  38. Init->destroyConstant();
  39. }
  40. GV.removeDeadConstantUsers();
  41. GV.setLinkage(GlobalValue::ExternalLinkage);
  42. NumVariables++;
  43. Changed = true;
  44. }
  45. // Drop the bodies of available externally functions.
  46. for (Function &F : M) {
  47. if (!F.hasAvailableExternallyLinkage())
  48. continue;
  49. if (!F.isDeclaration())
  50. // This will set the linkage to external
  51. F.deleteBody();
  52. F.removeDeadConstantUsers();
  53. NumFunctions++;
  54. Changed = true;
  55. }
  56. return Changed;
  57. }
  58. PreservedAnalyses
  59. EliminateAvailableExternallyPass::run(Module &M, ModuleAnalysisManager &) {
  60. if (!eliminateAvailableExternally(M))
  61. return PreservedAnalyses::all();
  62. return PreservedAnalyses::none();
  63. }
  64. namespace {
  65. struct EliminateAvailableExternallyLegacyPass : public ModulePass {
  66. static char ID; // Pass identification, replacement for typeid
  67. EliminateAvailableExternallyLegacyPass() : ModulePass(ID) {
  68. initializeEliminateAvailableExternallyLegacyPassPass(
  69. *PassRegistry::getPassRegistry());
  70. }
  71. // run - Do the EliminateAvailableExternally pass on the specified module,
  72. // optionally updating the specified callgraph to reflect the changes.
  73. bool runOnModule(Module &M) override {
  74. if (skipModule(M))
  75. return false;
  76. return eliminateAvailableExternally(M);
  77. }
  78. };
  79. } // end anonymous namespace
  80. char EliminateAvailableExternallyLegacyPass::ID = 0;
  81. INITIALIZE_PASS(EliminateAvailableExternallyLegacyPass, "elim-avail-extern",
  82. "Eliminate Available Externally Globals", false, false)
  83. ModulePass *llvm::createEliminateAvailableExternallyPass() {
  84. return new EliminateAvailableExternallyLegacyPass();
  85. }