LLVM  16.0.0git
CtorUtils.cpp
Go to the documentation of this file.
1 //===- CtorUtils.cpp - Helpers for working with global_ctors ----*- C++ -*-===//
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 file defines functions that are used to process llvm.global_ctors.
10 //
11 //===----------------------------------------------------------------------===//
12 
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/Module.h"
19 #include "llvm/Support/Debug.h"
21 #include <numeric>
22 
23 #define DEBUG_TYPE "ctor_utils"
24 
25 using namespace llvm;
26 
27 /// Given a specified llvm.global_ctors list, remove the listed elements.
28 static void removeGlobalCtors(GlobalVariable *GCL, const BitVector &CtorsToRemove) {
29  // Filter out the initializer elements to remove.
30  ConstantArray *OldCA = cast<ConstantArray>(GCL->getInitializer());
32  for (unsigned I = 0, E = OldCA->getNumOperands(); I < E; ++I)
33  if (!CtorsToRemove.test(I))
34  CAList.push_back(OldCA->getOperand(I));
35 
36  // Create the new array initializer.
37  ArrayType *ATy =
38  ArrayType::get(OldCA->getType()->getElementType(), CAList.size());
39  Constant *CA = ConstantArray::get(ATy, CAList);
40 
41  // If we didn't change the number of elements, don't create a new GV.
42  if (CA->getType() == OldCA->getType()) {
43  GCL->setInitializer(CA);
44  return;
45  }
46 
47  // Create the new global and insert it next to the existing list.
48  GlobalVariable *NGV =
49  new GlobalVariable(CA->getType(), GCL->isConstant(), GCL->getLinkage(),
50  CA, "", GCL->getThreadLocalMode());
51  GCL->getParent()->getGlobalList().insert(GCL->getIterator(), NGV);
52  NGV->takeName(GCL);
53 
54  // Nuke the old list, replacing any uses with the new one.
55  if (!GCL->use_empty()) {
56  Constant *V = NGV;
57  if (V->getType() != GCL->getType())
58  V = ConstantExpr::getBitCast(V, GCL->getType());
59  GCL->replaceAllUsesWith(V);
60  }
61  GCL->eraseFromParent();
62 }
63 
64 /// Given a llvm.global_ctors list that we can understand,
65 /// return a list of the functions and null terminator as a vector.
66 static std::vector<std::pair<uint32_t, Function *>>
68  ConstantArray *CA = cast<ConstantArray>(GV->getInitializer());
69  std::vector<std::pair<uint32_t, Function *>> Result;
70  Result.reserve(CA->getNumOperands());
71  for (auto &V : CA->operands()) {
72  ConstantStruct *CS = cast<ConstantStruct>(V);
73  Result.emplace_back(cast<ConstantInt>(CS->getOperand(0))->getZExtValue(),
74  dyn_cast<Function>(CS->getOperand(1)));
75  }
76  return Result;
77 }
78 
79 /// Find the llvm.global_ctors list.
81  GlobalVariable *GV = M.getGlobalVariable("llvm.global_ctors");
82  if (!GV)
83  return nullptr;
84 
85  // Verify that the initializer is simple enough for us to handle. We are
86  // only allowed to optimize the initializer if it is unique.
87  if (!GV->hasUniqueInitializer())
88  return nullptr;
89 
90  // If there are no ctors, then the initializer might be null/undef/poison.
91  // Ignore anything but an array.
92  ConstantArray *CA = dyn_cast<ConstantArray>(GV->getInitializer());
93  if (!CA)
94  return nullptr;
95 
96  for (auto &V : CA->operands()) {
97  if (isa<ConstantAggregateZero>(V))
98  continue;
99  ConstantStruct *CS = cast<ConstantStruct>(V);
100  if (isa<ConstantPointerNull>(CS->getOperand(1)))
101  continue;
102 
103  // Can only handle global constructors with no arguments.
104  Function *F = dyn_cast<Function>(CS->getOperand(1));
105  if (!F || F->arg_size() != 0)
106  return nullptr;
107  }
108  return GV;
109 }
110 
111 /// Call "ShouldRemove" for every entry in M's global_ctor list and remove the
112 /// entries for which it returns true. Return true if anything changed.
114  Module &M, function_ref<bool(uint32_t, Function *)> ShouldRemove) {
115  GlobalVariable *GlobalCtors = findGlobalCtors(M);
116  if (!GlobalCtors)
117  return false;
118 
119  std::vector<std::pair<uint32_t, Function *>> Ctors =
120  parseGlobalCtors(GlobalCtors);
121  if (Ctors.empty())
122  return false;
123 
124  bool MadeChange = false;
125  // Loop over global ctors, optimizing them when we can.
126  BitVector CtorsToRemove(Ctors.size());
127  std::vector<size_t> CtorsByPriority(Ctors.size());
128  std::iota(CtorsByPriority.begin(), CtorsByPriority.end(), 0);
129  stable_sort(CtorsByPriority, [&](size_t LHS, size_t RHS) {
130  return Ctors[LHS].first < Ctors[RHS].first;
131  });
132  for (unsigned CtorIndex : CtorsByPriority) {
133  const uint32_t Priority = Ctors[CtorIndex].first;
134  Function *F = Ctors[CtorIndex].second;
135  if (!F)
136  continue;
137 
138  LLVM_DEBUG(dbgs() << "Optimizing Global Constructor: " << *F << "\n");
139 
140  // If we can evaluate the ctor at compile time, do.
141  if (ShouldRemove(Priority, F)) {
142  Ctors[CtorIndex].second = nullptr;
143  CtorsToRemove.set(CtorIndex);
144  MadeChange = true;
145  continue;
146  }
147  }
148 
149  if (!MadeChange)
150  return false;
151 
152  removeGlobalCtors(GlobalCtors, CtorsToRemove);
153  return true;
154 }
llvm::GlobalVariable::eraseFromParent
void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
Definition: Globals.cpp:457
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::GlobalVariable::hasUniqueInitializer
bool hasUniqueInitializer() const
hasUniqueInitializer - Whether the global variable has an initializer, and any changes made to the in...
Definition: GlobalVariable.h:121
M
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Definition: README.txt:252
llvm::User::operands
op_range operands()
Definition: User.h:242
llvm::GlobalValue::getLinkage
LinkageTypes getLinkage() const
Definition: GlobalValue.h:525
llvm::Function
Definition: Function.h:60
llvm::BitVector::set
BitVector & set()
Definition: BitVector.h:344
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1183
llvm::GlobalVariable
Definition: GlobalVariable.h:39
llvm::ConstantExpr::getBitCast
static Constant * getBitCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
Definition: Constants.cpp:2199
Module.h
CtorUtils.h
RHS
Value * RHS
Definition: X86PartialReduction.cpp:76
llvm::ArrayType
Class to represent array types.
Definition: DerivedTypes.h:357
llvm::Module::getGlobalList
const GlobalListType & getGlobalList() const
Get the Module's list of global variables (constant).
Definition: Module.h:550
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
F
#define F(x, y, z)
Definition: MD5.cpp:55
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
LHS
Value * LHS
Definition: X86PartialReduction.cpp:75
Constants.h
removeGlobalCtors
static void removeGlobalCtors(GlobalVariable *GCL, const BitVector &CtorsToRemove)
Given a specified llvm.global_ctors list, remove the listed elements.
Definition: CtorUtils.cpp:28
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::GlobalValue::getThreadLocalMode
ThreadLocalMode getThreadLocalMode() const
Definition: GlobalValue.h:257
llvm::ConstantArray
ConstantArray - Constant Array Declarations.
Definition: Constants.h:410
BitVector.h
llvm::BitVector
Definition: BitVector.h:75
llvm::Value::use_empty
bool use_empty() const
Definition: Value.h:344
llvm::function_ref
An efficient, type-erasing, non-owning reference to a callable.
Definition: STLFunctionalExtras.h:36
llvm::ConstantArray::getType
ArrayType * getType() const
Specialize the getType() method to always return an ArrayType, which reduces the amount of casting ne...
Definition: Constants.h:429
llvm::GlobalVariable::getInitializer
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
Definition: GlobalVariable.h:135
llvm::Constant
This is an important base class in LLVM.
Definition: Constant.h:41
llvm::GlobalValue::getParent
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:636
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::ArrayType::get
static ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
Definition: Type.cpp:638
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
llvm::ConstantStruct
Definition: Constants.h:442
llvm::Value::getType
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:255
llvm::Value::replaceAllUsesWith
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:532
uint32_t
llvm::ilist_node_impl::getIterator
self_iterator getIterator()
Definition: ilist_node.h:82
llvm::BitVector::test
bool test(unsigned Idx) const
Definition: BitVector.h:454
llvm::stable_sort
void stable_sort(R &&Range)
Definition: STLExtras.h:1762
GlobalVariable.h
findGlobalCtors
static GlobalVariable * findGlobalCtors(Module &M)
Find the llvm.global_ctors list.
Definition: CtorUtils.cpp:80
Function.h
llvm::ConstantArray::get
static Constant * get(ArrayType *T, ArrayRef< Constant * > V)
Definition: Constants.cpp:1241
llvm::optimizeGlobalCtorsList
bool optimizeGlobalCtorsList(Module &M, function_ref< bool(uint32_t, Function *)> ShouldRemove)
Call "ShouldRemove" for every entry in M's global_ctor list and remove the entries for which it retur...
Definition: CtorUtils.cpp:113
llvm::User::getNumOperands
unsigned getNumOperands() const
Definition: User.h:191
llvm::GlobalVariable::isConstant
bool isConstant() const
If the value is a global constant, its value is immutable throughout the runtime execution of the pro...
Definition: GlobalVariable.h:152
llvm::GlobalValue::getType
PointerType * getType() const
Global values are always pointers.
Definition: GlobalValue.h:276
llvm::Value::takeName
void takeName(Value *V)
Transfer the name from V to this value.
Definition: Value.cpp:381
llvm::User::getOperand
Value * getOperand(unsigned i) const
Definition: User.h:169
raw_ostream.h
parseGlobalCtors
static std::vector< std::pair< uint32_t, Function * > > parseGlobalCtors(GlobalVariable *GV)
Given a llvm.global_ctors list that we can understand, return a list of the functions and null termin...
Definition: CtorUtils.cpp:67
Debug.h
llvm::ArrayType::getElementType
Type * getElementType() const
Definition: DerivedTypes.h:370
llvm::GlobalVariable::setInitializer
void setInitializer(Constant *InitVal)
setInitializer - Sets the initializer for this global variable, removing any existing initializer if ...
Definition: Globals.cpp:461