forked from OSchip/llvm-project
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:
parent
4f6a75809c
commit
fd4de79d2b
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue