riccibruno created this revision.
riccibruno added a reviewer: rsmith.
riccibruno added a project: clang.
Herald added a reviewer: shafik.
Herald added a subscriber: cfe-commits.
The vast majority of `CharacterLiteral`s have a value which fits into 8 bits
(in the 2666 `CharacterLiteral`s in all of Boost, only 2 don't).
When possible, use the space in the bit-fields of `Stmt` to store the value
and otherwise store it in a trailing object.
This saves 1 pointer per `CharacterLiteral` when the value fits into 8 bits.
Note that in itself this do not save that much space, but this is part of
a larger effort to pack the statements/expressions classes.
Repository:
rC Clang
https://reviews.llvm.org/D54324
Files:
include/clang/AST/Expr.h
include/clang/AST/Stmt.h
lib/AST/ASTImporter.cpp
lib/AST/Expr.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/SemaTemplate.cpp
lib/Serialization/ASTReaderStmt.cpp
Index: lib/Serialization/ASTReaderStmt.cpp
===================================================================
--- lib/Serialization/ASTReaderStmt.cpp
+++ lib/Serialization/ASTReaderStmt.cpp
@@ -636,8 +636,8 @@
void ASTStmtReader::VisitCharacterLiteral(CharacterLiteral *E) {
VisitExpr(E);
E->setValue(Record.readInt());
- E->setLocation(ReadSourceLocation());
- E->setKind(static_cast<CharacterLiteral::CharacterKind>(Record.readInt()));
+ E->CharacterLiteralBits.Loc = ReadSourceLocation();
+ E->CharacterLiteralBits.Kind = Record.readInt();
}
void ASTStmtReader::VisitParenExpr(ParenExpr *E) {
@@ -2454,7 +2454,10 @@
break;
case EXPR_CHARACTER_LITERAL:
- S = new (Context) CharacterLiteral(Empty);
+ S = CharacterLiteral::CreateEmpty(
+ Context,
+ /* IsSmallValue=*/CharacterLiteral::isSmallValue(
+ Record[ASTStmtReader::NumExprFields + 0]));
break;
case EXPR_PAREN:
Index: lib/Sema/SemaTemplate.cpp
===================================================================
--- lib/Sema/SemaTemplate.cpp
+++ lib/Sema/SemaTemplate.cpp
@@ -6865,8 +6865,9 @@
else
Kind = CharacterLiteral::Ascii;
- E = new (Context) CharacterLiteral(Arg.getAsIntegral().getZExtValue(),
- Kind, T, Loc);
+ E = CharacterLiteral::Create(Context, Arg.getAsIntegral().getZExtValue(),
+ Kind, T, Loc);
+
} else if (T->isBooleanType()) {
E = new (Context) CXXBoolLiteralExpr(Arg.getAsIntegral().getBoolValue(),
T, Loc);
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -3139,8 +3139,8 @@
else if (Literal.isUTF8())
Kind = CharacterLiteral::UTF8;
- Expr *Lit = new (Context) CharacterLiteral(Literal.getValue(), Kind, Ty,
- Tok.getLocation());
+ Expr *Lit = CharacterLiteral::Create(Context, Literal.getValue(), Kind, Ty,
+ Tok.getLocation());
if (Literal.getUDSuffix().empty())
return Lit;
Index: lib/AST/Expr.cpp
===================================================================
--- lib/AST/Expr.cpp
+++ lib/AST/Expr.cpp
@@ -815,6 +815,37 @@
return S.str();
}
+CharacterLiteral::CharacterLiteral(unsigned Value, CharacterKind Kind,
+ QualType Type, SourceLocation Loc)
+ : Expr(CharacterLiteralClass, Type, VK_RValue, OK_Ordinary, false, false,
+ false, false) {
+ CharacterLiteralBits.Kind = Kind;
+ CharacterLiteralBits.Loc = Loc;
+ CharacterLiteralBits.IsSmallValue = isSmallValue(Value);
+ setValue(Value);
+}
+
+CharacterLiteral::CharacterLiteral(EmptyShell Empty, bool IsSmallValue)
+ : Expr(CharacterLiteralClass, Empty) {
+ CharacterLiteralBits.IsSmallValue = IsSmallValue;
+}
+
+CharacterLiteral *CharacterLiteral::Create(const ASTContext &Ctx,
+ unsigned Value, CharacterKind Kind,
+ QualType Type, SourceLocation Loc) {
+ bool IsSmallValue = isSmallValue(Value);
+ void *Mem = Ctx.Allocate(totalSizeToAlloc<unsigned>(!IsSmallValue),
+ alignof(CharacterLiteral));
+ return new (Mem) CharacterLiteral(Value, Kind, Type, Loc);
+}
+
+CharacterLiteral *CharacterLiteral::CreateEmpty(const ASTContext &Ctx,
+ bool IsSmallValue) {
+ void *Mem = Ctx.Allocate(totalSizeToAlloc<unsigned>(!IsSmallValue),
+ alignof(CharacterLiteral));
+ return new (Mem) CharacterLiteral(EmptyShell(), IsSmallValue);
+}
+
FloatingLiteral::FloatingLiteral(const ASTContext &C, const llvm::APFloat &V,
bool isexact, QualType Type, SourceLocation L)
: Expr(FloatingLiteralClass, Type, VK_RValue, OK_Ordinary, false, false,
Index: lib/AST/ASTImporter.cpp
===================================================================
--- lib/AST/ASTImporter.cpp
+++ lib/AST/ASTImporter.cpp
@@ -6289,8 +6289,8 @@
if (!ToLocationOrErr)
return ToLocationOrErr.takeError();
- return new (Importer.getToContext()) CharacterLiteral(
- E->getValue(), E->getKind(), *ToTypeOrErr, *ToLocationOrErr);
+ return CharacterLiteral::Create(Importer.getToContext(), E->getValue(),
+ E->getKind(), *ToTypeOrErr, *ToLocationOrErr);
}
ExpectedStmt ASTNodeImporter::VisitStringLiteral(StringLiteral *E) {
Index: include/clang/AST/Stmt.h
===================================================================
--- include/clang/AST/Stmt.h
+++ include/clang/AST/Stmt.h
@@ -361,11 +361,21 @@
};
class CharacterLiteralBitfields {
+ friend class ASTStmtReader;
friend class CharacterLiteral;
unsigned : NumExprBits;
unsigned Kind : 3;
+
+ /// The vast majority of character literals have a value which fits into
+ /// 8 bits. In this case this value is stored here and IsSmallValue
+ /// is true. Otherwise, the value is stored as a trailing object and
+ /// IsSmallValue is false.
+ unsigned SmallValue : 8;
+ unsigned IsSmallValue : 1;
+
+ SourceLocation Loc;
};
enum APFloatSemantics {
Index: include/clang/AST/Expr.h
===================================================================
--- include/clang/AST/Expr.h
+++ include/clang/AST/Expr.h
@@ -1396,45 +1396,69 @@
}
};
-class CharacterLiteral : public Expr {
+class CharacterLiteral final
+ : public Expr,
+ private llvm::TrailingObjects<CharacterLiteral, unsigned> {
+ friend class ASTReader;
+ friend class ASTStmtReader;
+ friend TrailingObjects;
+
public:
- enum CharacterKind {
- Ascii,
- Wide,
- UTF8,
- UTF16,
- UTF32
- };
+ enum CharacterKind { Ascii, Wide, UTF8, UTF16, UTF32 };
private:
- unsigned Value;
- SourceLocation Loc;
-public:
- // type should be IntTy
- CharacterLiteral(unsigned value, CharacterKind kind, QualType type,
- SourceLocation l)
- : Expr(CharacterLiteralClass, type, VK_RValue, OK_Ordinary, false, false,
- false, false),
- Value(value), Loc(l) {
- CharacterLiteralBits.Kind = kind;
+ // The vast majority of character literals have a value which fits into
+ // 8 bits. For this reason in the common case the value is stored inline
+ // in CharacterLiteralBits and isSmallValue() is true. Otherwise the
+ // value is stored in a trailing unsigned and isSmallValue() is false.
+ // Note that the kind of the character literal do not matter for this.
+ // It is therefore perfectly possible to have an UTF32 character literal
+ // with its value stored inline, as long as the value is <= MaxSmallValue.
+ enum { MaxSmallValue = 255 };
+ static bool isSmallValue(unsigned Val) { return Val <= MaxSmallValue; }
+
+ /// True if the value of this character literal is stored inline.
+ bool isSmallValue() const { return CharacterLiteralBits.IsSmallValue; }
+
+
+ void setValue(unsigned Val) {
+ if (isSmallValue()) {
+ assert(isSmallValue(Val) &&
+ "This value is too large to be stored in this CharacterLiteral!");
+ CharacterLiteralBits.SmallValue = Val;
+ } else
+ *getTrailingObjects<unsigned>() = Val;
}
- /// Construct an empty character literal.
- CharacterLiteral(EmptyShell Empty) : Expr(CharacterLiteralClass, Empty) { }
+ // Build a character literal.
+ CharacterLiteral(unsigned Value, CharacterKind Kind, QualType Type,
+ SourceLocation Loc);
- SourceLocation getLocation() const { return Loc; }
+ /// Build an empty character literal.
+ CharacterLiteral(EmptyShell Empty, bool IsSmallValue);
+
+public:
+ /// Create a character literal.
+ static CharacterLiteral *Create(const ASTContext &Ctx, unsigned Value,
+ CharacterKind Kind, QualType Type,
+ SourceLocation Loc);
+
+ /// Create a character literal, optionally with storage for a large value.
+ static CharacterLiteral *CreateEmpty(const ASTContext &Ctx,
+ bool IsSmallValue);
+
+ SourceLocation getLocation() const { return CharacterLiteralBits.Loc; }
CharacterKind getKind() const {
return static_cast<CharacterKind>(CharacterLiteralBits.Kind);
}
- SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; }
- SourceLocation getEndLoc() const LLVM_READONLY { return Loc; }
-
- unsigned getValue() const { return Value; }
+ SourceLocation getBeginLoc() const { return getLocation(); }
+ SourceLocation getEndLoc() const { return getLocation(); }
- void setLocation(SourceLocation Location) { Loc = Location; }
- void setKind(CharacterKind kind) { CharacterLiteralBits.Kind = kind; }
- void setValue(unsigned Val) { Value = Val; }
+ unsigned getValue() const {
+ return isSmallValue() ? CharacterLiteralBits.SmallValue
+ : *getTrailingObjects<unsigned>();
+ }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CharacterLiteralClass;
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits