aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/IR/Function.cpp
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2017-03-17 17:16:39 +0000
committerReid Kleckner <rnk@google.com>2017-03-17 17:16:39 +0000
commit56d028d9744b045974fd2a52c296318018c30f9f (patch)
treeb45cf8b96299b4b23ec0ceaa24737fa2a9d99399 /llvm/lib/IR/Function.cpp
parentee2dd785f617101cc7f02e7fb192761154867327 (diff)
downloadllvm-56d028d9744b045974fd2a52c296318018c30f9f.zip
llvm-56d028d9744b045974fd2a52c296318018c30f9f.tar.gz
llvm-56d028d9744b045974fd2a52c296318018c30f9f.tar.bz2
Store Arguments in a flat array instead of an iplist
This saves two pointers from Argument and eliminates some extra allocations. Arguments cannot be inserted or removed from a Function because that would require changing its Type, which LLVM does not allow. Instead, passes that change prototypes, like DeadArgElim, create a new Function and copy over argument names and attributes. The primary benefit of iplist is O(1) random insertion and removal. We just don't need that for arguments, so don't use it. Reviewed By: chandlerc Subscribers: dlj, inglorion, llvm-commits Differential Revision: https://reviews.llvm.org/D31058 llvm-svn: 298105
Diffstat (limited to 'llvm/lib/IR/Function.cpp')
-rw-r--r--llvm/lib/IR/Function.cpp60
1 files changed, 46 insertions, 14 deletions
diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp
index 6e1b476..c384ec9 100644
--- a/llvm/lib/IR/Function.cpp
+++ b/llvm/lib/IR/Function.cpp
@@ -30,7 +30,6 @@ using namespace llvm;
// Explicit instantiations of SymbolTableListTraits since some of the methods
// are not in the public header file...
-template class llvm::SymbolTableListTraits<Argument>;
template class llvm::SymbolTableListTraits<BasicBlock>;
//===----------------------------------------------------------------------===//
@@ -39,8 +38,8 @@ template class llvm::SymbolTableListTraits<BasicBlock>;
void Argument::anchor() { }
-Argument::Argument(Type *Ty, const Twine &Name, unsigned ArgNo)
- : Value(Ty, Value::ArgumentVal), Parent(nullptr), ArgNo(ArgNo) {
+Argument::Argument(Type *Ty, const Twine &Name, Function *Par, unsigned ArgNo)
+ : Value(Ty, Value::ArgumentVal), Parent(Par), ArgNo(ArgNo) {
setName(Name);
}
@@ -188,7 +187,8 @@ void Function::eraseFromParent() {
Function::Function(FunctionType *Ty, LinkageTypes Linkage, const Twine &name,
Module *ParentModule)
: GlobalObject(Ty, Value::FunctionVal,
- OperandTraits<Function>::op_begin(this), 0, Linkage, name) {
+ OperandTraits<Function>::op_begin(this), 0, Linkage, name),
+ Arguments(nullptr), NumArgs(Ty->getNumParams()) {
assert(FunctionType::isValidReturnType(getReturnType()) &&
"invalid return type");
setGlobalObjectSubClassData(0);
@@ -216,7 +216,8 @@ Function::~Function() {
dropAllReferences(); // After this it is safe to delete instructions.
// Delete all of the method arguments and unlink from symbol table...
- ArgumentList.clear();
+ if (Arguments)
+ clearArguments();
// Remove the function from the on-the-side GC table.
clearGC();
@@ -224,17 +225,33 @@ Function::~Function() {
void Function::BuildLazyArguments() const {
// Create the arguments vector, all arguments start out unnamed.
- FunctionType *FT = getFunctionType();
- for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
- assert(!FT->getParamType(i)->isVoidTy() &&
- "Cannot have void typed arguments!");
- ArgumentList.push_back(
- new Argument(FT->getParamType(i), "", i));
+ auto *FT = getFunctionType();
+ if (NumArgs > 0) {
+ Arguments = std::allocator<Argument>().allocate(NumArgs);
+ for (unsigned i = 0, e = NumArgs; i != e; ++i) {
+ Type *ArgTy = FT->getParamType(i);
+ assert(!ArgTy->isVoidTy() && "Cannot have void typed arguments!");
+ new (Arguments + i) Argument(ArgTy, "", const_cast<Function *>(this), i);
+ }
}
// Clear the lazy arguments bit.
unsigned SDC = getSubclassDataFromValue();
const_cast<Function*>(this)->setValueSubclassData(SDC &= ~(1<<0));
+ assert(!hasLazyArguments());
+}
+
+static MutableArrayRef<Argument> makeArgArray(Argument *Args, size_t Count) {
+ return MutableArrayRef<Argument>(Args, Count);
+}
+
+void Function::clearArguments() {
+ for (Argument &A : makeArgArray(Arguments, NumArgs)) {
+ A.setName("");
+ A.~Argument();
+ }
+ std::allocator<Argument>().deallocate(Arguments, NumArgs);
+ Arguments = nullptr;
}
void Function::stealArgumentListFrom(Function &Src) {
@@ -242,10 +259,10 @@ void Function::stealArgumentListFrom(Function &Src) {
// Drop the current arguments, if any, and set the lazy argument bit.
if (!hasLazyArguments()) {
- assert(llvm::all_of(ArgumentList,
+ assert(llvm::all_of(makeArgArray(Arguments, NumArgs),
[](const Argument &A) { return A.use_empty(); }) &&
"Expected arguments to be unused in declaration");
- ArgumentList.clear();
+ clearArguments();
setValueSubclassData(getSubclassDataFromValue() | (1 << 0));
}
@@ -254,8 +271,23 @@ void Function::stealArgumentListFrom(Function &Src) {
return;
// Steal arguments from Src, and fix the lazy argument bits.
- ArgumentList.splice(ArgumentList.end(), Src.ArgumentList);
+ assert(arg_size() == Src.arg_size());
+ Arguments = Src.Arguments;
+ Src.Arguments = nullptr;
+ for (Argument &A : makeArgArray(Arguments, NumArgs)) {
+ // FIXME: This does the work of transferNodesFromList inefficiently.
+ SmallString<128> Name;
+ if (A.hasName())
+ Name = A.getName();
+ if (!Name.empty())
+ A.setName("");
+ A.setParent(this);
+ if (!Name.empty())
+ A.setName(Name);
+ }
+
setValueSubclassData(getSubclassDataFromValue() & ~(1 << 0));
+ assert(!hasLazyArguments());
Src.setValueSubclassData(Src.getSubclassDataFromValue() | (1 << 0));
}