Eliminate "obviously braindead" canonicalization of function types, using

a foldingset instead.  This reduces the number of slow type lookups from
32K to 10K, which speeds up parsing of carbon.h from 11s to 3.5s.

llvm-svn: 39311
This commit is contained in:
Chris Lattner 2007-01-27 01:15:32 +00:00
parent 4f6a75809c
commit fd4de79d2b
4 changed files with 32 additions and 24 deletions

View File

@ -203,27 +203,16 @@ TypeRef ASTContext::getFunctionTypeNoProto(TypeRef ResultTy) {
/// list. isVariadic indicates whether the argument list includes '...'.
TypeRef ASTContext::getFunctionType(TypeRef ResultTy, TypeRef *ArgArray,
unsigned NumArgs, bool isVariadic) {
// FIXME: This is obviously braindead!
// Unique functions, to guarantee there is only one function of a particular
// structure.
++NumSlowLookups;
for (unsigned i = 0, e = Types.size(); i != e; ++i) {
if (FunctionTypeProto *FTy = dyn_cast<FunctionTypeProto>(Types[i]))
if (FTy->getResultType() == ResultTy &&
FTy->getNumArgs() == NumArgs &&
FTy->isVariadic() == isVariadic) {
bool Match = true;
for (unsigned arg = 0; arg != NumArgs; ++arg) {
if (FTy->getArgType(arg) != ArgArray[arg]) {
Match = false;
break;
}
}
if (Match)
return Types[i];
}
}
FoldingSetNodeID ID;
FunctionTypeProto::Profile(ID, ResultTy, ArgArray, NumArgs, isVariadic);
void *InsertPos = 0;
if (FunctionTypeProto *FTP =
FunctionTypeProtos.FindNodeOrInsertPos(ID, InsertPos))
return FTP;
// Determine whether the type being created is already canonical or not.
bool isCanonical = ResultTy->isCanonical();
for (unsigned i = 0; i != NumArgs && isCanonical; ++i)
@ -241,6 +230,11 @@ TypeRef ASTContext::getFunctionType(TypeRef ResultTy, TypeRef *ArgArray,
Canonical = getFunctionType(ResultTy.getCanonicalType(),
&CanonicalArgs[0], NumArgs,
isVariadic).getTypePtr();
// Get the new insert position for the node we care about.
FunctionTypeProto *NewIP =
FunctionTypeProtos.FindNodeOrInsertPos(ID, InsertPos);
assert(NewIP == 0 && "Shouldn't be in the map!");
}
// FunctionTypeProto objects are not allocated with new because they have a
@ -252,6 +246,7 @@ TypeRef ASTContext::getFunctionType(TypeRef ResultTy, TypeRef *ArgArray,
Canonical);
Types.push_back(FTP);
FunctionTypeProtos.InsertNode(FTP, InsertPos);
return FTP;
}

View File

@ -75,6 +75,15 @@ const char *BuiltinType::getName() const {
}
}
void FunctionTypeProto::Profile(FoldingSetNodeID &ID, TypeRef Result,
TypeRef* ArgTys,
unsigned NumArgs, bool isVariadic) {
ID.AddPointer(Result.getAsOpaquePtr());
for (unsigned i = 0; i != NumArgs; ++i)
ID.AddPointer(ArgTys[i].getAsOpaquePtr());
ID.AddInteger(isVariadic);
}
bool RecordType::classof(const Type *T) {
if (const TaggedType *TT = dyn_cast<TaggedType>(T))
return isa<RecordDecl>(TT->getDecl());

View File

@ -25,9 +25,9 @@ namespace clang {
/// ASTContext - This class holds long-lived AST nodes (such as types and
/// decls) that can be referred to throughout the semantic analysis of a file.
class ASTContext {
// FIXME: This is a stupid data structure.
std::vector<Type*> Types;
unsigned NumSlowLookups;
FoldingSet<FunctionTypeProto> FunctionTypeProtos;
public:
Preprocessor &PP;
TargetInfo &Target;

View File

@ -15,9 +15,7 @@
#define LLVM_CLANG_AST_TYPE_H
#include "llvm/Support/Casting.h"
#include "llvm/Support/DataTypes.h"
#include <cassert>
#include <string>
#include "llvm/ADT/FoldingSet.h"
namespace llvm {
namespace clang {
@ -325,7 +323,7 @@ public:
/// FunctionTypeProto - Represents a prototype with argument type info, e.g.
/// 'int foo(int)' or 'int foo(void)'. 'void' is represented as having no
/// arguments, not as having a single void argument.
class FunctionTypeProto : public FunctionType {
class FunctionTypeProto : public FunctionType, public FoldingSetNode {
FunctionTypeProto(TypeRef Result, TypeRef *ArgArray, unsigned numArgs,
bool isVariadic, Type *Canonical)
: FunctionType(FunctionProto, Result, isVariadic, Canonical),
@ -357,6 +355,12 @@ public:
return T->getTypeClass() == FunctionProto;
}
static bool classof(const FunctionTypeProto *) { return true; }
void Profile(FoldingSetNodeID &ID) {
Profile(ID, getResultType(), ArgInfo, NumArgs, isVariadic());
}
static void Profile(FoldingSetNodeID &ID, TypeRef Result, TypeRef* ArgTys,
unsigned NumArgs, bool isVariadic);
};