Skip to content

Commit f71bd1c

Browse files
authored
[clang][bytecode] Add Record::hasPtrField() (llvm#183513)
So we can short-circuit the checking in `EvaluationResult::collectBlock()`. This improves the compile time of `X86Disassembler.cpp` by roughly 3.8%: https://llvm-compile-time-tracker.com/compare_clang.php?from=d69c6a8528c60a8f8013651ff18ed4882f6e6836&to=b8b6333551d7c644e3c1b00ed19aceea09da40cc&stat=instructions%3Au
1 parent d43213f commit f71bd1c

4 files changed

Lines changed: 41 additions & 13 deletions

File tree

clang/lib/AST/ByteCode/EvaluationResult.cpp

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,15 @@ bool EvaluationResult::checkFullyInitialized(InterpState &S,
157157
return true;
158158
}
159159

160+
static bool isOrHasPtr(const Descriptor *D) {
161+
if ((D->isPrimitive() || D->isPrimitiveArray()) && D->getPrimType() == PT_Ptr)
162+
return true;
163+
164+
if (D->ElemRecord)
165+
return D->ElemRecord->hasPtrField();
166+
return false;
167+
}
168+
160169
static void collectBlocks(const Pointer &Ptr,
161170
llvm::SetVector<const Block *> &Blocks) {
162171
auto isUsefulPtr = [](const Pointer &P) -> bool {
@@ -173,26 +182,29 @@ static void collectBlocks(const Pointer &Ptr,
173182
if (!Desc)
174183
return;
175184

176-
if (const Record *R = Desc->ElemRecord) {
185+
if (const Record *R = Desc->ElemRecord; R && R->hasPtrField()) {
186+
177187
for (const Record::Field &F : R->fields()) {
178-
const Pointer &FieldPtr = Ptr.atField(F.Offset);
188+
if (!isOrHasPtr(F.Desc))
189+
continue;
190+
Pointer FieldPtr = Ptr.atField(F.Offset);
179191
assert(FieldPtr.block() == Ptr.block());
180192
collectBlocks(FieldPtr, Blocks);
181193
}
182194
} else if (Desc->isPrimitive() && Desc->getPrimType() == PT_Ptr) {
183-
const Pointer &Pointee = Ptr.deref<Pointer>();
195+
Pointer Pointee = Ptr.deref<Pointer>();
184196
if (isUsefulPtr(Pointee) && !Blocks.contains(Pointee.block()))
185197
collectBlocks(Pointee, Blocks);
186198

187199
} else if (Desc->isPrimitiveArray() && Desc->getPrimType() == PT_Ptr) {
188200
for (unsigned I = 0; I != Desc->getNumElems(); ++I) {
189-
const Pointer &ElemPointee = Ptr.elem<Pointer>(I);
201+
Pointer ElemPointee = Ptr.elem<Pointer>(I);
190202
if (isUsefulPtr(ElemPointee) && !Blocks.contains(ElemPointee.block()))
191203
collectBlocks(ElemPointee, Blocks);
192204
}
193-
} else if (Desc->isCompositeArray()) {
205+
} else if (Desc->isCompositeArray() && isOrHasPtr(Desc->ElemDesc)) {
194206
for (unsigned I = 0; I != Desc->getNumElems(); ++I) {
195-
const Pointer &ElemPtr = Ptr.atIndex(I).narrow();
207+
Pointer ElemPtr = Ptr.atIndex(I).narrow();
196208
collectBlocks(ElemPtr, Blocks);
197209
}
198210
}

clang/lib/AST/ByteCode/Program.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,7 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) {
356356
// Reserve space for fields.
357357
Record::FieldList Fields;
358358
Fields.reserve(RD->getNumFields());
359+
bool HasPtrField = false;
359360
for (const FieldDecl *FD : RD->fields()) {
360361
FD = FD->getFirstDecl();
361362
// Note that we DO create fields and descriptors
@@ -374,18 +375,22 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) {
374375
if (OptPrimType T = Ctx.classify(FT)) {
375376
Desc = createDescriptor(FD, *T, nullptr, std::nullopt, IsConst,
376377
/*isTemporary=*/false, IsMutable, IsVolatile);
378+
HasPtrField = HasPtrField || (T == PT_Ptr);
377379
} else {
378380
Desc = createDescriptor(FD, FT.getTypePtr(), std::nullopt, IsConst,
379381
/*isTemporary=*/false, IsMutable, IsVolatile);
382+
HasPtrField = HasPtrField || (Desc && Desc->isPrimitiveArray() &&
383+
Desc->getPrimType() == PT_Ptr);
380384
}
381385
if (!Desc)
382386
return nullptr;
383387
Fields.emplace_back(FD, Desc, BaseSize);
384388
BaseSize += align(Desc->getAllocSize());
385389
}
386390

387-
Record *R = new (Allocator) Record(RD, std::move(Bases), std::move(Fields),
388-
std::move(VirtBases), VirtSize, BaseSize);
391+
Record *R = new (Allocator)
392+
Record(RD, std::move(Bases), std::move(Fields), std::move(VirtBases),
393+
VirtSize, BaseSize, HasPtrField);
389394
Records[RD] = R;
390395
return R;
391396
}

clang/lib/AST/ByteCode/Record.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,24 @@ using namespace clang::interp;
1414

1515
Record::Record(const RecordDecl *Decl, BaseList &&SrcBases,
1616
FieldList &&SrcFields, VirtualBaseList &&SrcVirtualBases,
17-
unsigned VirtualSize, unsigned BaseSize)
17+
unsigned VirtualSize, unsigned BaseSize, bool HasPtrField)
1818
: Decl(Decl), Bases(std::move(SrcBases)), Fields(std::move(SrcFields)),
1919
BaseSize(BaseSize), VirtualSize(VirtualSize), IsUnion(Decl->isUnion()),
20-
IsAnonymousUnion(IsUnion && Decl->isAnonymousStructOrUnion()) {
20+
IsAnonymousUnion(IsUnion && Decl->isAnonymousStructOrUnion()),
21+
HasPtrField(HasPtrField) {
2122
for (Base &V : SrcVirtualBases)
2223
VirtualBases.emplace_back(V.Decl, V.Desc, V.R, V.Offset + BaseSize);
2324

24-
for (Base &B : Bases)
25+
for (Base &B : Bases) {
2526
BaseMap[B.Decl] = &B;
26-
for (Base &V : VirtualBases)
27+
if (!HasPtrField)
28+
HasPtrField |= B.R->hasPtrField();
29+
}
30+
for (Base &V : VirtualBases) {
2731
VirtualBaseMap[V.Decl] = &V;
32+
if (!HasPtrField)
33+
HasPtrField |= V.R->hasPtrField();
34+
}
2835
}
2936

3037
std::string Record::getName() const {

clang/lib/AST/ByteCode/Record.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ class Record final {
7575
return CXXDecl->getDestructor();
7676
return nullptr;
7777
}
78+
/// If this record (or any of its bases) contains a field of type PT_Ptr.
79+
bool hasPtrField() const { return HasPtrField; }
7880

7981
/// Returns true for anonymous unions and records
8082
/// with no destructor or for those with a trivial destructor.
@@ -125,7 +127,7 @@ class Record final {
125127
/// Constructor used by Program to create record descriptors.
126128
Record(const RecordDecl *, BaseList &&Bases, FieldList &&Fields,
127129
VirtualBaseList &&VirtualBases, unsigned VirtualSize,
128-
unsigned BaseSize);
130+
unsigned BaseSize, bool HasPtrField = true);
129131

130132
private:
131133
friend class Program;
@@ -151,6 +153,8 @@ class Record final {
151153
bool IsUnion;
152154
/// If this is an anonymous union.
153155
bool IsAnonymousUnion;
156+
/// If any of the fields are pointers (or references).
157+
bool HasPtrField = false;
154158
};
155159

156160
} // namespace interp

0 commit comments

Comments
 (0)