Skip to content

Commit e39ee62

Browse files
authored
[clang][bytecode] Use OptPrimType instead of std::optional<PrimType> (#149812)
We use this construct a lot. Use something similar to clang's UnsignedOrNone. This results in some slighy compile time improvements: https://llvm-compile-time-tracker.com/compare.php?from=17a4b0399d161a3b89d8f0ce82add1638f23f5d4&to=a251d81ecd0ed45dd190462663155fdb303ef04d&stat=instructions:u
1 parent 49d7a9b commit e39ee62

File tree

11 files changed

+120
-92
lines changed

11 files changed

+120
-92
lines changed

clang/lib/AST/ByteCode/ByteCodeEmitter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ void ByteCodeEmitter::compileFunc(const FunctionDecl *FuncDecl,
6262
(Func->hasThisPointer() && !Func->isThisPointerExplicit());
6363
for (auto ParamOffset : llvm::drop_begin(Func->ParamOffsets, Drop)) {
6464
const ParmVarDecl *PD = FuncDecl->parameters()[ParamIndex];
65-
std::optional<PrimType> T = Ctx.classify(PD->getType());
65+
OptPrimType T = Ctx.classify(PD->getType());
6666
this->Params.insert({PD, {ParamOffset, T != std::nullopt}});
6767
++ParamIndex;
6868
}

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 59 additions & 60 deletions
Large diffs are not rendered by default.

clang/lib/AST/ByteCode/Compiler.h

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -254,12 +254,8 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
254254
/// If the function does not exist yet, it is compiled.
255255
const Function *getFunction(const FunctionDecl *FD);
256256

257-
std::optional<PrimType> classify(const Expr *E) const {
258-
return Ctx.classify(E);
259-
}
260-
std::optional<PrimType> classify(QualType Ty) const {
261-
return Ctx.classify(Ty);
262-
}
257+
OptPrimType classify(const Expr *E) const { return Ctx.classify(E); }
258+
OptPrimType classify(QualType Ty) const { return Ctx.classify(Ty); }
263259

264260
/// Classifies a known primitive type.
265261
PrimType classifyPrim(QualType Ty) const {
@@ -306,7 +302,7 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
306302
bool visitInitList(ArrayRef<const Expr *> Inits, const Expr *ArrayFiller,
307303
const Expr *E);
308304
bool visitArrayElemInit(unsigned ElemIndex, const Expr *Init,
309-
std::optional<PrimType> InitT);
305+
OptPrimType InitT);
310306
bool visitCallArgs(ArrayRef<const Expr *> Args, const FunctionDecl *FuncDecl,
311307
bool Activate);
312308

@@ -435,7 +431,7 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
435431
bool InitStackActive = false;
436432

437433
/// Type of the expression returned by the function.
438-
std::optional<PrimType> ReturnType;
434+
OptPrimType ReturnType;
439435

440436
/// Switch case mapping.
441437
CaseMap CaseLabels;

clang/lib/AST/ByteCode/Context.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ static PrimType integralTypeToPrimTypeU(unsigned BitWidth) {
306306
llvm_unreachable("Unhandled BitWidth");
307307
}
308308

309-
std::optional<PrimType> Context::classify(QualType T) const {
309+
OptPrimType Context::classify(QualType T) const {
310310

311311
if (const auto *BT = dyn_cast<BuiltinType>(T.getCanonicalType())) {
312312
auto Kind = BT->getKind();
@@ -542,7 +542,7 @@ const Function *Context::getOrCreateFunction(const FunctionDecl *FuncDecl) {
542542
// Assign descriptors to all parameters.
543543
// Composite objects are lowered to pointers.
544544
for (const ParmVarDecl *PD : FuncDecl->parameters()) {
545-
std::optional<PrimType> T = classify(PD->getType());
545+
OptPrimType T = classify(PD->getType());
546546
PrimType PT = T.value_or(PT_Ptr);
547547
Descriptor *Desc = P->createDescriptor(PD, PT);
548548
ParamDescriptors.insert({ParamOffset, {PT, Desc}});
@@ -570,7 +570,7 @@ const Function *Context::getOrCreateObjCBlock(const BlockExpr *E) {
570570
// Assign descriptors to all parameters.
571571
// Composite objects are lowered to pointers.
572572
for (const ParmVarDecl *PD : BD->parameters()) {
573-
std::optional<PrimType> T = classify(PD->getType());
573+
OptPrimType T = classify(PD->getType());
574574
PrimType PT = T.value_or(PT_Ptr);
575575
Descriptor *Desc = P->createDescriptor(PD, PT);
576576
ParamDescriptors.insert({ParamOffset, {PT, Desc}});

clang/lib/AST/ByteCode/Context.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,10 @@ class Context final {
8282
uint32_t getBitWidth(QualType T) const { return Ctx.getIntWidth(T); }
8383

8484
/// Classifies a type.
85-
std::optional<PrimType> classify(QualType T) const;
85+
OptPrimType classify(QualType T) const;
8686

8787
/// Classifies an expression.
88-
std::optional<PrimType> classify(const Expr *E) const {
88+
OptPrimType classify(const Expr *E) const {
8989
assert(E);
9090
if (E->isGLValue())
9191
return PT_Ptr;

clang/lib/AST/ByteCode/Descriptor.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ struct Descriptor final {
164164
/// The primitive type this descriptor was created for,
165165
/// or the primitive element type in case this is
166166
/// a primitive array.
167-
const std::optional<PrimType> PrimT = std::nullopt;
167+
const OptPrimType PrimT = std::nullopt;
168168
/// Flag indicating if the block is mutable.
169169
const bool IsConst = false;
170170
/// Flag indicating if a field is mutable.

clang/lib/AST/ByteCode/EvalEmitter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ void EvalEmitter::updateGlobalTemporaries() {
324324
const Pointer &Ptr = P.getPtrGlobal(*GlobalIndex);
325325
APValue *Cached = Temp->getOrCreateValue(true);
326326

327-
if (std::optional<PrimType> T = Ctx.classify(E->getType())) {
327+
if (OptPrimType T = Ctx.classify(E->getType())) {
328328
TYPE_SWITCH(
329329
*T, { *Cached = Ptr.deref<T>().toAPValue(Ctx.getASTContext()); });
330330
} else {

clang/lib/AST/ByteCode/InterpBuiltin.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ static APSInt popToAPSInt(InterpStack &Stk, PrimType T) {
5353
static void pushInteger(InterpState &S, const APSInt &Val, QualType QT) {
5454
assert(QT->isSignedIntegerOrEnumerationType() ||
5555
QT->isUnsignedIntegerOrEnumerationType());
56-
std::optional<PrimType> T = S.getContext().classify(QT);
56+
OptPrimType T = S.getContext().classify(QT);
5757
assert(T);
5858

5959
unsigned BitWidth = S.getASTContext().getTypeSize(QT);
@@ -1530,7 +1530,7 @@ static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC,
15301530
return false;
15311531

15321532
bool IsArray = NumElems.ugt(1);
1533-
std::optional<PrimType> ElemT = S.getContext().classify(ElemType);
1533+
OptPrimType ElemT = S.getContext().classify(ElemType);
15341534
DynamicAllocator &Allocator = S.getAllocator();
15351535
if (ElemT) {
15361536
Block *B =
@@ -2879,7 +2879,7 @@ static bool copyRecord(InterpState &S, CodePtr OpPC, const Pointer &Src,
28792879

28802880
auto copyField = [&](const Record::Field &F, bool Activate) -> bool {
28812881
Pointer DestField = Dest.atField(F.Offset);
2882-
if (std::optional<PrimType> FT = S.Ctx.classify(F.Decl->getType())) {
2882+
if (OptPrimType FT = S.Ctx.classify(F.Decl->getType())) {
28832883
TYPE_SWITCH(*FT, {
28842884
DestField.deref<T>() = Src.atField(F.Offset).deref<T>();
28852885
if (Src.atField(F.Offset).isInitialized())

clang/lib/AST/ByteCode/Pointer.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -665,7 +665,7 @@ std::optional<APValue> Pointer::toRValue(const Context &Ctx,
665665
return false;
666666

667667
// Primitive values.
668-
if (std::optional<PrimType> T = Ctx.classify(Ty)) {
668+
if (OptPrimType T = Ctx.classify(Ty)) {
669669
TYPE_SWITCH(*T, R = Ptr.deref<T>().toAPValue(ASTCtx));
670670
return true;
671671
}
@@ -682,7 +682,7 @@ std::optional<APValue> Pointer::toRValue(const Context &Ctx,
682682
const Pointer &FP = Ptr.atField(F.Offset);
683683
QualType FieldTy = F.Decl->getType();
684684
if (FP.isActive()) {
685-
if (std::optional<PrimType> T = Ctx.classify(FieldTy)) {
685+
if (OptPrimType T = Ctx.classify(FieldTy)) {
686686
TYPE_SWITCH(*T, Value = FP.deref<T>().toAPValue(ASTCtx));
687687
} else {
688688
Ok &= Composite(FieldTy, FP, Value);
@@ -705,7 +705,7 @@ std::optional<APValue> Pointer::toRValue(const Context &Ctx,
705705
const Pointer &FP = Ptr.atField(FD->Offset);
706706
APValue &Value = R.getStructField(I);
707707

708-
if (std::optional<PrimType> T = Ctx.classify(FieldTy)) {
708+
if (OptPrimType T = Ctx.classify(FieldTy)) {
709709
TYPE_SWITCH(*T, Value = FP.deref<T>().toAPValue(ASTCtx));
710710
} else {
711711
Ok &= Composite(FieldTy, FP, Value);
@@ -743,7 +743,7 @@ std::optional<APValue> Pointer::toRValue(const Context &Ctx,
743743
for (unsigned I = 0; I < NumElems; ++I) {
744744
APValue &Slot = R.getArrayInitializedElt(I);
745745
const Pointer &EP = Ptr.atIndex(I);
746-
if (std::optional<PrimType> T = Ctx.classify(ElemTy)) {
746+
if (OptPrimType T = Ctx.classify(ElemTy)) {
747747
TYPE_SWITCH(*T, Slot = EP.deref<T>().toAPValue(ASTCtx));
748748
} else {
749749
Ok &= Composite(ElemTy, EP.narrow(), Slot);
@@ -757,7 +757,7 @@ std::optional<APValue> Pointer::toRValue(const Context &Ctx,
757757
QualType ElemTy = CT->getElementType();
758758

759759
if (ElemTy->isIntegerType()) {
760-
std::optional<PrimType> ElemT = Ctx.classify(ElemTy);
760+
OptPrimType ElemT = Ctx.classify(ElemTy);
761761
assert(ElemT);
762762
INT_TYPE_SWITCH(*ElemT, {
763763
auto V1 = Ptr.elem<T>(0);
@@ -803,7 +803,7 @@ std::optional<APValue> Pointer::toRValue(const Context &Ctx,
803803
return toAPValue(ASTCtx);
804804

805805
// Just load primitive types.
806-
if (std::optional<PrimType> T = Ctx.classify(ResultType)) {
806+
if (OptPrimType T = Ctx.classify(ResultType)) {
807807
TYPE_SWITCH(*T, return this->deref<T>().toAPValue(ASTCtx));
808808
}
809809

clang/lib/AST/ByteCode/PrimType.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#ifndef LLVM_CLANG_AST_INTERP_TYPE_H
1414
#define LLVM_CLANG_AST_INTERP_TYPE_H
1515

16+
#include "clang/Basic/UnsignedOrNone.h"
1617
#include "llvm/Support/raw_ostream.h"
1718
#include <climits>
1819
#include <cstddef>
@@ -49,6 +50,38 @@ enum PrimType : unsigned {
4950
PT_MemberPtr = 14,
5051
};
5152

53+
// Like std::optional<PrimType>, but only sizeof(PrimType).
54+
class OptPrimType final {
55+
unsigned V = ~0u;
56+
57+
public:
58+
OptPrimType() = default;
59+
OptPrimType(std::nullopt_t) {}
60+
OptPrimType(PrimType T) : V(static_cast<unsigned>(T)) {}
61+
62+
explicit constexpr operator bool() const { return V != ~0u; }
63+
PrimType operator*() const {
64+
assert(operator bool());
65+
return static_cast<PrimType>(V);
66+
}
67+
68+
PrimType value_or(PrimType PT) const {
69+
if (operator bool())
70+
return static_cast<PrimType>(V);
71+
return PT;
72+
}
73+
74+
bool operator==(PrimType PT) const {
75+
if (!operator bool())
76+
return false;
77+
return V == static_cast<unsigned>(PT);
78+
}
79+
bool operator==(OptPrimType OPT) const { return V == OPT.V; }
80+
bool operator!=(PrimType PT) const { return !(*this == PT); }
81+
bool operator!=(OptPrimType OPT) const { return V != OPT.V; }
82+
};
83+
static_assert(sizeof(OptPrimType) == sizeof(PrimType));
84+
5285
inline constexpr bool isPtrType(PrimType T) {
5386
return T == PT_Ptr || T == PT_MemberPtr;
5487
}

0 commit comments

Comments
 (0)