CtorUtils.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. //===- CtorUtils.cpp - Helpers for working with global_ctors ----*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file defines functions that are used to process llvm.global_ctors.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "llvm/Transforms/Utils/CtorUtils.h"
  14. #include "llvm/ADT/BitVector.h"
  15. #include "llvm/IR/Constants.h"
  16. #include "llvm/IR/Function.h"
  17. #include "llvm/IR/GlobalVariable.h"
  18. #include "llvm/IR/Instructions.h"
  19. #include "llvm/IR/Module.h"
  20. #include "llvm/Support/Debug.h"
  21. #include "llvm/Support/raw_ostream.h"
  22. #define DEBUG_TYPE "ctor_utils"
  23. namespace llvm {
  24. namespace {
  25. /// Given a specified llvm.global_ctors list, remove the listed elements.
  26. void removeGlobalCtors(GlobalVariable *GCL, const BitVector &CtorsToRemove) {
  27. // Filter out the initializer elements to remove.
  28. ConstantArray *OldCA = cast<ConstantArray>(GCL->getInitializer());
  29. SmallVector<Constant *, 10> CAList;
  30. for (unsigned I = 0, E = OldCA->getNumOperands(); I < E; ++I)
  31. if (!CtorsToRemove.test(I))
  32. CAList.push_back(OldCA->getOperand(I));
  33. // Create the new array initializer.
  34. ArrayType *ATy =
  35. ArrayType::get(OldCA->getType()->getElementType(), CAList.size());
  36. Constant *CA = ConstantArray::get(ATy, CAList);
  37. // If we didn't change the number of elements, don't create a new GV.
  38. if (CA->getType() == OldCA->getType()) {
  39. GCL->setInitializer(CA);
  40. return;
  41. }
  42. // Create the new global and insert it next to the existing list.
  43. GlobalVariable *NGV =
  44. new GlobalVariable(CA->getType(), GCL->isConstant(), GCL->getLinkage(),
  45. CA, "", GCL->getThreadLocalMode());
  46. GCL->getParent()->getGlobalList().insert(GCL, NGV);
  47. NGV->takeName(GCL);
  48. // Nuke the old list, replacing any uses with the new one.
  49. if (!GCL->use_empty()) {
  50. Constant *V = NGV;
  51. if (V->getType() != GCL->getType())
  52. V = ConstantExpr::getBitCast(V, GCL->getType());
  53. GCL->replaceAllUsesWith(V);
  54. }
  55. GCL->eraseFromParent();
  56. }
  57. /// Given a llvm.global_ctors list that we can understand,
  58. /// return a list of the functions and null terminator as a vector.
  59. std::vector<Function *> parseGlobalCtors(GlobalVariable *GV) {
  60. if (GV->getInitializer()->isNullValue())
  61. return std::vector<Function *>();
  62. ConstantArray *CA = cast<ConstantArray>(GV->getInitializer());
  63. std::vector<Function *> Result;
  64. Result.reserve(CA->getNumOperands());
  65. for (User::op_iterator i = CA->op_begin(), e = CA->op_end(); i != e; ++i) {
  66. ConstantStruct *CS = cast<ConstantStruct>(*i);
  67. Result.push_back(dyn_cast<Function>(CS->getOperand(1)));
  68. }
  69. return Result;
  70. }
  71. /// Find the llvm.global_ctors list, verifying that all initializers have an
  72. /// init priority of 65535.
  73. GlobalVariable *findGlobalCtors(Module &M) {
  74. GlobalVariable *GV = M.getGlobalVariable("llvm.global_ctors");
  75. if (!GV)
  76. return nullptr;
  77. // Verify that the initializer is simple enough for us to handle. We are
  78. // only allowed to optimize the initializer if it is unique.
  79. if (!GV->hasUniqueInitializer())
  80. return nullptr;
  81. if (isa<ConstantAggregateZero>(GV->getInitializer()))
  82. return GV;
  83. ConstantArray *CA = cast<ConstantArray>(GV->getInitializer());
  84. for (User::op_iterator i = CA->op_begin(), e = CA->op_end(); i != e; ++i) {
  85. if (isa<ConstantAggregateZero>(*i))
  86. continue;
  87. ConstantStruct *CS = cast<ConstantStruct>(*i);
  88. if (isa<ConstantPointerNull>(CS->getOperand(1)))
  89. continue;
  90. // Must have a function or null ptr.
  91. if (!isa<Function>(CS->getOperand(1)))
  92. return nullptr;
  93. // Init priority must be standard.
  94. ConstantInt *CI = cast<ConstantInt>(CS->getOperand(0));
  95. if (CI->getZExtValue() != 65535)
  96. return nullptr;
  97. }
  98. return GV;
  99. }
  100. } // namespace
  101. /// Call "ShouldRemove" for every entry in M's global_ctor list and remove the
  102. /// entries for which it returns true. Return true if anything changed.
  103. bool optimizeGlobalCtorsList(Module &M,
  104. function_ref<bool(Function *)> ShouldRemove) {
  105. GlobalVariable *GlobalCtors = findGlobalCtors(M);
  106. if (!GlobalCtors)
  107. return false;
  108. std::vector<Function *> Ctors = parseGlobalCtors(GlobalCtors);
  109. if (Ctors.empty())
  110. return false;
  111. bool MadeChange = false;
  112. // Loop over global ctors, optimizing them when we can.
  113. unsigned NumCtors = Ctors.size();
  114. BitVector CtorsToRemove(NumCtors);
  115. for (unsigned i = 0; i != Ctors.size() && NumCtors > 0; ++i) {
  116. Function *F = Ctors[i];
  117. // Found a null terminator in the middle of the list, prune off the rest of
  118. // the list.
  119. if (!F)
  120. continue;
  121. DEBUG(dbgs() << "Optimizing Global Constructor: " << *F << "\n");
  122. // We cannot simplify external ctor functions.
  123. if (F->empty())
  124. continue;
  125. // If we can evaluate the ctor at compile time, do.
  126. if (ShouldRemove(F)) {
  127. Ctors[i] = nullptr;
  128. CtorsToRemove.set(i);
  129. NumCtors--;
  130. MadeChange = true;
  131. continue;
  132. }
  133. }
  134. if (!MadeChange)
  135. return false;
  136. removeGlobalCtors(GlobalCtors, CtorsToRemove);
  137. return true;
  138. }
  139. } // End llvm namespace