Skip to content
This repository has been archived by the owner on Apr 23, 2020. It is now read-only.

Commit

Permalink
[Sema] Implement __make_integer_seq
Browse files Browse the repository at this point in the history
This new builtin template allows for incredibly fast instantiations of
templates like std::integer_sequence.

Performance numbers follow:
My work station has 64 GB of ram + 20 Xeon Cores at 2.8 GHz.

__make_integer_seq<std::integer_sequence, int, 90000> takes 0.25
seconds.

std::make_integer_sequence<int, 90000> takes unbound time, it is still
running.  Clang is consuming gigabytes of memory.

Differential Revision: http://reviews.llvm.org/D13786

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@252036 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
majnemer committed Nov 4, 2015
1 parent 0c29653 commit 6bb02a2
Show file tree
Hide file tree
Showing 23 changed files with 308 additions and 4 deletions.
15 changes: 15 additions & 0 deletions include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ namespace clang {
class VTableContextBase;

namespace Builtin { class Context; }
enum BuiltinTemplateKind : int;

namespace comments {
class FullComment;
Expand Down Expand Up @@ -246,6 +247,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// The identifier 'NSCopying'.
IdentifierInfo *NSCopyingName = nullptr;

/// The identifier '__make_integer_seq'.
mutable IdentifierInfo *MakeIntegerSeqName = nullptr;

QualType ObjCConstantStringType;
mutable RecordDecl *CFConstantStringTypeDecl;

Expand Down Expand Up @@ -399,6 +403,7 @@ class ASTContext : public RefCountedBase<ASTContext> {

TranslationUnitDecl *TUDecl;
mutable ExternCContextDecl *ExternCContext;
mutable BuiltinTemplateDecl *MakeIntegerSeqDecl;

/// \brief The associated SourceManager object.a
SourceManager &SourceMgr;
Expand Down Expand Up @@ -868,6 +873,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; }

ExternCContextDecl *getExternCContextDecl() const;
BuiltinTemplateDecl *getMakeIntegerSeqDecl() const;

// Builtin Types.
CanQualType VoidTy;
Expand Down Expand Up @@ -941,6 +947,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
void PrintStats() const;
const SmallVectorImpl<Type *>& getTypes() const { return Types; }

BuiltinTemplateDecl *buildBuiltinTemplateDecl(BuiltinTemplateKind BTK,
const IdentifierInfo *II) const;

/// \brief Create a new implicit TU-level CXXRecordDecl or RecordDecl
/// declaration.
RecordDecl *buildImplicitRecord(StringRef Name,
Expand Down Expand Up @@ -1444,6 +1453,12 @@ class ASTContext : public RefCountedBase<ASTContext> {
return NSCopyingName;
}

IdentifierInfo *getMakeIntegerSeqName() const {
if (!MakeIntegerSeqName)
MakeIntegerSeqName = &Idents.get("__make_integer_seq");
return MakeIntegerSeqName;
}

/// \brief Retrieve the Objective-C "instancetype" type, if already known;
/// otherwise, returns a NULL type;
QualType getObjCInstanceType() {
Expand Down
4 changes: 4 additions & 0 deletions include/clang/AST/DataRecursiveASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -1551,6 +1551,10 @@ DEF_TRAVERSE_DECL(FunctionTemplateDecl, {
TRY_TO(TraverseFunctionInstantiations(D));
})

DEF_TRAVERSE_DECL(BuiltinTemplateDecl, {
TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
})

DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, {
// D is the "T" in something like
// template <template <typename> class T> class container { };
Expand Down
30 changes: 30 additions & 0 deletions include/clang/AST/DeclTemplate.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

namespace clang {

enum BuiltinTemplateKind : int;
class TemplateParameterList;
class TemplateDecl;
class RedeclarableTemplateDecl;
Expand Down Expand Up @@ -1490,6 +1491,35 @@ class TemplateTemplateParmDecl final
friend TrailingObjects;
};

/// \brief Represents the builtin template declaration which is used to
/// implement __make_integer_seq. It serves no real purpose beyond existing as
/// a place to hold template parameters.
class BuiltinTemplateDecl : public TemplateDecl {
void anchor() override;

BuiltinTemplateDecl(const ASTContext &C, DeclContext *DC,
DeclarationName Name, BuiltinTemplateKind BTK);

BuiltinTemplateKind BTK;

public:
// Implement isa/cast/dyncast support
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == BuiltinTemplate; }

static BuiltinTemplateDecl *Create(const ASTContext &C, DeclContext *DC,
DeclarationName Name,
BuiltinTemplateKind BTK) {
return new (C, DC) BuiltinTemplateDecl(C, DC, Name, BTK);
}

SourceRange getSourceRange() const override LLVM_READONLY {
return SourceRange();
}

BuiltinTemplateKind getBuiltinTemplateKind() const { return BTK; }
};

/// \brief Represents a class template specialization, which refers to
/// a class template with a given set of template arguments.
///
Expand Down
4 changes: 4 additions & 0 deletions include/clang/AST/RecursiveASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -1603,6 +1603,10 @@ DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, {
TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
})

DEF_TRAVERSE_DECL(BuiltinTemplateDecl, {
TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
})

DEF_TRAVERSE_DECL(TemplateTypeParmDecl, {
// D is the "T" in something like "template<typename T> class vector;"
if (D->getTypeForDecl())
Expand Down
7 changes: 7 additions & 0 deletions include/clang/Basic/Builtins.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,5 +205,12 @@ class Context {
};

}

/// \brief Kinds of BuiltinTemplateDecl.
enum BuiltinTemplateKind : int {
/// \brief This names the __make_integer_seq BuiltinTemplateDecl.
BTK__make_integer_seq
};

} // end namespace clang
#endif
1 change: 1 addition & 0 deletions include/clang/Basic/DeclNodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ def Named : Decl<1>;
def VarTemplate : DDecl<RedeclarableTemplate>;
def TypeAliasTemplate : DDecl<RedeclarableTemplate>;
def TemplateTemplateParm : DDecl<Template>;
def BuiltinTemplate : DDecl<Template>;
def Using : DDecl<Named>;
def UsingShadow : DDecl<Named>;
def ObjCMethod : DDecl<Named>, DeclContext;
Expand Down
8 changes: 7 additions & 1 deletion include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -1995,7 +1995,13 @@ def err_concept_decl_invalid_specifiers : Error<
def warn_cxx98_compat_unicode_type : Warning<
"'%0' type specifier is incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;


// __make_integer_seq
def err_integer_sequence_negative_length : Error<
"integer sequences must have non-negative sequence length">;
def err_integer_sequence_integral_element_type : Error<
"integer sequences must have integral element type">;

// Objective-C++
def err_objc_decls_may_only_appear_in_global_scope : Error<
"Objective-C declarations may only appear in global scope">;
Expand Down
5 changes: 4 additions & 1 deletion include/clang/Serialization/ASTBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -982,13 +982,16 @@ namespace clang {

/// \brief The extern "C" context.
PREDEF_DECL_EXTERN_C_CONTEXT_ID = 12,

/// \brief The internal '__make_integer_seq' template.
PREDEF_DECL_MAKE_INTEGER_SEQ_ID = 13,
};

/// \brief The number of declaration IDs that are predefined.
///
/// For more information about predefined declarations, see the
/// \c PredefinedDeclIDs type and the PREDEF_DECL_*_ID constants.
const unsigned int NUM_PREDEF_DECL_IDS = 13;
const unsigned int NUM_PREDEF_DECL_IDS = 14;

/// \brief Record code for a list of local redeclarations of a declaration.
const unsigned int LOCAL_REDECLARATIONS = 50;
Expand Down
20 changes: 19 additions & 1 deletion lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -744,7 +744,7 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM,
ucontext_tDecl(nullptr), BlockDescriptorType(nullptr),
BlockDescriptorExtendedType(nullptr), cudaConfigureCallDecl(nullptr),
FirstLocalImport(), LastLocalImport(), ExternCContext(nullptr),
SourceMgr(SM), LangOpts(LOpts),
MakeIntegerSeqDecl(nullptr), SourceMgr(SM), LangOpts(LOpts),
SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFiles, SM)),
AddrSpaceMap(nullptr), Target(nullptr), AuxTarget(nullptr),
PrintingPolicy(LOpts), Idents(idents), Selectors(sels),
Expand Down Expand Up @@ -913,6 +913,24 @@ ExternCContextDecl *ASTContext::getExternCContextDecl() const {
return ExternCContext;
}

BuiltinTemplateDecl *
ASTContext::buildBuiltinTemplateDecl(BuiltinTemplateKind BTK,
const IdentifierInfo *II) const {
auto *BuiltinTemplate = BuiltinTemplateDecl::Create(*this, TUDecl, II, BTK);
BuiltinTemplate->setImplicit();
TUDecl->addDecl(BuiltinTemplate);

return BuiltinTemplate;
}

BuiltinTemplateDecl *
ASTContext::getMakeIntegerSeqDecl() const {
if (!MakeIntegerSeqDecl)
MakeIntegerSeqDecl = buildBuiltinTemplateDecl(BTK__make_integer_seq,
getMakeIntegerSeqName());
return MakeIntegerSeqDecl;
}

RecordDecl *ASTContext::buildImplicitRecord(StringRef Name,
RecordDecl::TagKind TK) const {
SourceLocation Loc;
Expand Down
7 changes: 7 additions & 0 deletions lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/TypeVisitor.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/Support/raw_ostream.h"
Expand Down Expand Up @@ -447,6 +448,7 @@ namespace {
const ClassTemplatePartialSpecializationDecl *D);
void VisitClassScopeFunctionSpecializationDecl(
const ClassScopeFunctionSpecializationDecl *D);
void VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D);
void VisitVarTemplateDecl(const VarTemplateDecl *D);
void VisitVarTemplateSpecializationDecl(
const VarTemplateSpecializationDecl *D);
Expand Down Expand Up @@ -1333,6 +1335,11 @@ void ASTDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) {
VisitTemplateDecl(D, false);
}

void ASTDumper::VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D) {
dumpName(D);
dumpTemplateParameters(D->getTemplateParameters());
}

void ASTDumper::VisitVarTemplateSpecializationDecl(
const VarTemplateSpecializationDecl *D) {
dumpTemplateArgumentList(D->getTemplateArgs());
Expand Down
1 change: 1 addition & 0 deletions lib/AST/DeclBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case ExternCContext:

case UsingDirective:
case BuiltinTemplate:
case ClassTemplateSpecialization:
case ClassTemplatePartialSpecialization:
case ClassScopeFunctionSpecialization:
Expand Down
67 changes: 67 additions & 0 deletions lib/AST/DeclTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/IdentifierTable.h"
#include "llvm/ADT/STLExtras.h"
#include <memory>
Expand Down Expand Up @@ -1191,3 +1192,69 @@ VarTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
return new (C, ID) VarTemplatePartialSpecializationDecl(C);
}

static TemplateParameterList *
createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) {
// typename T
auto *T = TemplateTypeParmDecl::Create(
C, DC, SourceLocation(), SourceLocation(), /*Depth=*/1, /*Position=*/0,
/*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/false);
T->setImplicit(true);

// T ...Ints
TypeSourceInfo *TI =
C.getTrivialTypeSourceInfo(QualType(T->getTypeForDecl(), 0));
auto *N = NonTypeTemplateParmDecl::Create(
C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/1,
/*Id=*/nullptr, TI->getType(), /*ParameterPack=*/true, TI);
N->setImplicit(true);

// <typename T, T ...Ints>
NamedDecl *P[2] = {T, N};
auto *TPL = TemplateParameterList::Create(
C, SourceLocation(), SourceLocation(), P, 2, SourceLocation());

// template <typename T, ...Ints> class IntSeq
auto *TemplateTemplateParm = TemplateTemplateParmDecl::Create(
C, DC, SourceLocation(), /*Depth=*/0, /*Position=*/0,
/*ParameterPack=*/false, /*Id=*/nullptr, TPL);
TemplateTemplateParm->setImplicit(true);

// typename T
auto *TemplateTypeParm = TemplateTypeParmDecl::Create(
C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/1,
/*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/false);
TemplateTypeParm->setImplicit(true);

// T N
TypeSourceInfo *TInfo = C.getTrivialTypeSourceInfo(
QualType(TemplateTypeParm->getTypeForDecl(), 0));
auto *NonTypeTemplateParm = NonTypeTemplateParmDecl::Create(
C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/2,
/*Id=*/nullptr, TInfo->getType(), /*ParameterPack=*/false, TInfo);
NamedDecl *Params[] = {TemplateTemplateParm, TemplateTypeParm,
NonTypeTemplateParm};

// template <template <typename T, T ...Ints> class IntSeq, typename T, T N>
return TemplateParameterList::Create(C, SourceLocation(), SourceLocation(),
Params, 3, SourceLocation());
}

static TemplateParameterList *createBuiltinTemplateParameterList(
const ASTContext &C, DeclContext *DC, BuiltinTemplateKind BTK) {
switch (BTK) {
case BTK__make_integer_seq:
return createMakeIntegerSeqParameterList(C, DC);
}

llvm_unreachable("unhandled BuiltinTemplateKind!");
}

void BuiltinTemplateDecl::anchor() {}

BuiltinTemplateDecl::BuiltinTemplateDecl(const ASTContext &C, DeclContext *DC,
DeclarationName Name,
BuiltinTemplateKind BTK)
: TemplateDecl(BuiltinTemplate, DC, SourceLocation(), Name,
createBuiltinTemplateParameterList(C, DC, BTK)),
BTK(BTK) {}
1 change: 1 addition & 0 deletions lib/CodeGen/CGDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ using namespace CodeGen;

void CodeGenFunction::EmitDecl(const Decl &D) {
switch (D.getKind()) {
case Decl::BuiltinTemplate:
case Decl::TranslationUnit:
case Decl::ExternCContext:
case Decl::Namespace:
Expand Down
5 changes: 5 additions & 0 deletions lib/Sema/SemaLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,11 @@ static bool LookupBuiltin(Sema &S, LookupResult &R) {
R.addDecl(S.getASTContext().getFloat128StubType());
return true;
}
if (S.getLangOpts().CPlusPlus && NameKind == Sema::LookupOrdinaryName &&
II == S.getASTContext().getMakeIntegerSeqName()) {
R.addDecl(S.getASTContext().getMakeIntegerSeqDecl());
return true;
}

// If this is a builtin on this (or all) targets, create the decl.
if (unsigned BuiltinID = II->getBuiltinID()) {
Expand Down

0 comments on commit 6bb02a2

Please sign in to comment.