aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Utils/CtorUtils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/Utils/CtorUtils.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/CtorUtils.cpp65
1 files changed, 30 insertions, 35 deletions
diff --git a/llvm/lib/Transforms/Utils/CtorUtils.cpp b/llvm/lib/Transforms/Utils/CtorUtils.cpp
index 069a86f6ab33..c997f39508e3 100644
--- a/llvm/lib/Transforms/Utils/CtorUtils.cpp
+++ b/llvm/lib/Transforms/Utils/CtorUtils.cpp
@@ -18,6 +18,7 @@
#include "llvm/IR/Module.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
+#include <numeric>
#define DEBUG_TYPE "ctor_utils"
@@ -62,21 +63,20 @@ static void removeGlobalCtors(GlobalVariable *GCL, const BitVector &CtorsToRemov
/// Given a llvm.global_ctors list that we can understand,
/// return a list of the functions and null terminator as a vector.
-static std::vector<Function *> parseGlobalCtors(GlobalVariable *GV) {
- if (GV->getInitializer()->isNullValue())
- return std::vector<Function *>();
+static std::vector<std::pair<uint32_t, Function *>>
+parseGlobalCtors(GlobalVariable *GV) {
ConstantArray *CA = cast<ConstantArray>(GV->getInitializer());
- std::vector<Function *> Result;
+ std::vector<std::pair<uint32_t, Function *>> Result;
Result.reserve(CA->getNumOperands());
for (auto &V : CA->operands()) {
ConstantStruct *CS = cast<ConstantStruct>(V);
- Result.push_back(dyn_cast<Function>(CS->getOperand(1)));
+ Result.emplace_back(cast<ConstantInt>(CS->getOperand(0))->getZExtValue(),
+ dyn_cast<Function>(CS->getOperand(1)));
}
return Result;
}
-/// Find the llvm.global_ctors list, verifying that all initializers have an
-/// init priority of 65535.
+/// Find the llvm.global_ctors list.
static GlobalVariable *findGlobalCtors(Module &M) {
GlobalVariable *GV = M.getGlobalVariable("llvm.global_ctors");
if (!GV)
@@ -87,9 +87,11 @@ static GlobalVariable *findGlobalCtors(Module &M) {
if (!GV->hasUniqueInitializer())
return nullptr;
- if (isa<ConstantAggregateZero>(GV->getInitializer()))
- return GV;
- ConstantArray *CA = cast<ConstantArray>(GV->getInitializer());
+ // If there are no ctors, then the initializer might be null/undef/poison.
+ // Ignore anything but an array.
+ ConstantArray *CA = dyn_cast<ConstantArray>(GV->getInitializer());
+ if (!CA)
+ return nullptr;
for (auto &V : CA->operands()) {
if (isa<ConstantAggregateZero>(V))
@@ -98,54 +100,47 @@ static GlobalVariable *findGlobalCtors(Module &M) {
if (isa<ConstantPointerNull>(CS->getOperand(1)))
continue;
- // Must have a function or null ptr.
- if (!isa<Function>(CS->getOperand(1)))
- return nullptr;
-
- // Init priority must be standard.
- ConstantInt *CI = cast<ConstantInt>(CS->getOperand(0));
- if (CI->getZExtValue() != 65535)
+ // Can only handle global constructors with no arguments.
+ Function *F = dyn_cast<Function>(CS->getOperand(1));
+ if (!F || F->arg_size() != 0)
return nullptr;
}
-
return GV;
}
/// Call "ShouldRemove" for every entry in M's global_ctor list and remove the
/// entries for which it returns true. Return true if anything changed.
bool llvm::optimizeGlobalCtorsList(
- Module &M, function_ref<bool(Function *)> ShouldRemove) {
+ Module &M, function_ref<bool(uint32_t, Function *)> ShouldRemove) {
GlobalVariable *GlobalCtors = findGlobalCtors(M);
if (!GlobalCtors)
return false;
- std::vector<Function *> Ctors = parseGlobalCtors(GlobalCtors);
+ std::vector<std::pair<uint32_t, Function *>> Ctors =
+ parseGlobalCtors(GlobalCtors);
if (Ctors.empty())
return false;
bool MadeChange = false;
-
// Loop over global ctors, optimizing them when we can.
- unsigned NumCtors = Ctors.size();
- BitVector CtorsToRemove(NumCtors);
- for (unsigned i = 0; i != Ctors.size() && NumCtors > 0; ++i) {
- Function *F = Ctors[i];
- // Found a null terminator in the middle of the list, prune off the rest of
- // the list.
+ BitVector CtorsToRemove(Ctors.size());
+ std::vector<size_t> CtorsByPriority(Ctors.size());
+ std::iota(CtorsByPriority.begin(), CtorsByPriority.end(), 0);
+ stable_sort(CtorsByPriority, [&](size_t LHS, size_t RHS) {
+ return Ctors[LHS].first < Ctors[RHS].first;
+ });
+ for (unsigned CtorIndex : CtorsByPriority) {
+ const uint32_t Priority = Ctors[CtorIndex].first;
+ Function *F = Ctors[CtorIndex].second;
if (!F)
continue;
LLVM_DEBUG(dbgs() << "Optimizing Global Constructor: " << *F << "\n");
- // We cannot simplify external ctor functions.
- if (F->empty())
- continue;
-
// If we can evaluate the ctor at compile time, do.
- if (ShouldRemove(F)) {
- Ctors[i] = nullptr;
- CtorsToRemove.set(i);
- NumCtors--;
+ if (ShouldRemove(Priority, F)) {
+ Ctors[CtorIndex].second = nullptr;
+ CtorsToRemove.set(CtorIndex);
MadeChange = true;
continue;
}