LLVM  14.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 
22 #define DEBUG_TYPE "ctor_utils"
23 
24 using namespace llvm;
25 
26 /// Given a specified llvm.global_ctors list, remove the listed elements.
27 static void removeGlobalCtors(GlobalVariable *GCL, const BitVector &CtorsToRemove) {
28  // Filter out the initializer elements to remove.
29  ConstantArray *OldCA = cast<ConstantArray>(GCL->getInitializer());
31  for (unsigned I = 0, E = OldCA->getNumOperands(); I < E; ++I)
32  if (!CtorsToRemove.test(I))
33  CAList.push_back(OldCA->getOperand(I));
34 
35  // Create the new array initializer.
36  ArrayType *ATy =
37  ArrayType::get(OldCA->getType()->getElementType(), CAList.size());
38  Constant *CA = ConstantArray::get(ATy, CAList);
39 
40  // If we didn't change the number of elements, don't create a new GV.
41  if (CA->getType() == OldCA->getType()) {
42  GCL->setInitializer(CA);
43  return;
44  }
45 
46  // Create the new global and insert it next to the existing list.
47  GlobalVariable *NGV =
48  new GlobalVariable(CA->getType(), GCL->isConstant(), GCL->getLinkage(),
49  CA, "", GCL->getThreadLocalMode());
50  GCL->getParent()->getGlobalList().insert(GCL->getIterator(), NGV);
51  NGV->takeName(GCL);
52 
53  // Nuke the old list, replacing any uses with the new one.
54  if (!GCL->use_empty()) {
55  Constant *V = NGV;
56  if (V->getType() != GCL->getType())
57  V = ConstantExpr::getBitCast(V, GCL->getType());
58  GCL->replaceAllUsesWith(V);
59  }
60  GCL->eraseFromParent();
61 }
62 
63 /// Given a llvm.global_ctors list that we can understand,
64 /// return a list of the functions and null terminator as a vector.
65 static std::vector<Function *> parseGlobalCtors(GlobalVariable *GV) {
66  if (GV->getInitializer()->isNullValue())
67  return std::vector<Function *>();
68  ConstantArray *CA = cast<ConstantArray>(GV->getInitializer());
69  std::vector<Function *> Result;
70  Result.reserve(CA->getNumOperands());
71  for (auto &V : CA->operands()) {
72  ConstantStruct *CS = cast<ConstantStruct>(V);
73  Result.push_back(dyn_cast<Function>(CS->getOperand(1)));
74  }
75  return Result;
76 }
77 
78 /// Find the llvm.global_ctors list, verifying that all initializers have an
79 /// init priority of 65535.
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 (isa<ConstantAggregateZero>(GV->getInitializer()))
91  return GV;
92  ConstantArray *CA = cast<ConstantArray>(GV->getInitializer());
93 
94  for (auto &V : CA->operands()) {
95  if (isa<ConstantAggregateZero>(V))
96  continue;
97  ConstantStruct *CS = cast<ConstantStruct>(V);
98  if (isa<ConstantPointerNull>(CS->getOperand(1)))
99  continue;
100 
101  // Must have a function or null ptr.
102  if (!isa<Function>(CS->getOperand(1)))
103  return nullptr;
104 
105  // Init priority must be standard.
106  ConstantInt *CI = cast<ConstantInt>(CS->getOperand(0));
107  if (CI->getZExtValue() != 65535)
108  return nullptr;
109  }
110 
111  return GV;
112 }
113 
114 /// Call "ShouldRemove" for every entry in M's global_ctor list and remove the
115 /// entries for which it returns true. Return true if anything changed.
117  Module &M, function_ref<bool(Function *)> ShouldRemove) {
118  GlobalVariable *GlobalCtors = findGlobalCtors(M);
119  if (!GlobalCtors)
120  return false;
121 
122  std::vector<Function *> Ctors = parseGlobalCtors(GlobalCtors);
123  if (Ctors.empty())
124  return false;
125 
126  bool MadeChange = false;
127 
128  // Loop over global ctors, optimizing them when we can.
129  unsigned NumCtors = Ctors.size();
130  BitVector CtorsToRemove(NumCtors);
131  for (unsigned i = 0; i != Ctors.size() && NumCtors > 0; ++i) {
132  Function *F = Ctors[i];
133  // Found a null terminator in the middle of the list, prune off the rest of
134  // the list.
135  if (!F)
136  continue;
137 
138  LLVM_DEBUG(dbgs() << "Optimizing Global Constructor: " << *F << "\n");
139 
140  // We cannot simplify external ctor functions.
141  if (F->empty())
142  continue;
143 
144  // If we can evaluate the ctor at compile time, do.
145  if (ShouldRemove(F)) {
146  Ctors[i] = nullptr;
147  CtorsToRemove.set(i);
148  NumCtors--;
149  MadeChange = true;
150  continue;
151  }
152  }
153 
154  if (!MadeChange)
155  return false;
156 
157  removeGlobalCtors(GlobalCtors, CtorsToRemove);
158  return true;
159 }
i
i
Definition: README.txt:29
llvm::GlobalVariable::eraseFromParent
void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
Definition: Globals.cpp:385
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
llvm::GlobalVariable::hasUniqueInitializer
bool hasUniqueInitializer() const
hasUniqueInitializer - Whether the global variable has an initializer, and any changes made to the in...
Definition: GlobalVariable.h:122
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::optimizeGlobalCtorsList
bool optimizeGlobalCtorsList(Module &M, function_ref< bool(Function *)> ShouldRemove)
Call "ShouldRemove" for every entry in M's global_ctor list and remove the entries for which it retur...
Definition: CtorUtils.cpp:116
llvm::GlobalValue::getLinkage
LinkageTypes getLinkage() const
Definition: GlobalValue.h:461
llvm::Function
Definition: Function.h:61
llvm::BitVector::set
BitVector & set()
Definition: BitVector.h:343
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1168
llvm::GlobalVariable
Definition: GlobalVariable.h:40
llvm::ConstantExpr::getBitCast
static Constant * getBitCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
Definition: Constants.cpp:2208
Module.h
CtorUtils.h
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:547
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
F
#define F(x, y, z)
Definition: MD5.cpp:56
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
llvm::ConstantInt
This is the shared class of boolean and integer constants.
Definition: Constants.h:79
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:27
llvm::Constant::isNullValue
bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
Definition: Constants.cpp:74
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::GlobalValue::getThreadLocalMode
ThreadLocalMode getThreadLocalMode() const
Definition: GlobalValue.h:252
llvm::ConstantArray
ConstantArray - Constant Array Declarations.
Definition: Constants.h:409
BitVector.h
llvm::BitVector
Definition: BitVector.h:74
llvm::Value::use_empty
bool use_empty() const
Definition: Value.h:345
llvm::function_ref
An efficient, type-erasing, non-owning reference to a callable.
Definition: STLExtras.h:168
parseGlobalCtors
static std::vector< 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:65
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:428
llvm::GlobalVariable::getInitializer
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
Definition: GlobalVariable.h:136
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:572
I
#define I(x, y, z)
Definition: MD5.cpp:59
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:602
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
llvm::ConstantStruct
Definition: Constants.h:441
llvm::Value::getType
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:256
llvm::Value::replaceAllUsesWith
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:532
llvm::ilist_node_impl::getIterator
self_iterator getIterator()
Definition: ilist_node.h:81
llvm::ConstantInt::getZExtValue
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
Definition: Constants.h:142
llvm::BitVector::test
bool test(unsigned Idx) const
Definition: BitVector.h:447
GlobalVariable.h
findGlobalCtors
static GlobalVariable * findGlobalCtors(Module &M)
Find the llvm.global_ctors list, verifying that all initializers have an init priority of 65535.
Definition: CtorUtils.cpp:80
Function.h
llvm::ConstantArray::get
static Constant * get(ArrayType *T, ArrayRef< Constant * > V)
Definition: Constants.cpp:1263
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:153
llvm::GlobalValue::getType
PointerType * getType() const
Global values are always pointers.
Definition: GlobalValue.h:271
llvm::Value::takeName
void takeName(Value *V)
Transfer the name from V to this value.
Definition: Value.cpp:382
llvm::User::getOperand
Value * getOperand(unsigned i) const
Definition: User.h:169
raw_ostream.h
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:389