Use range-based for to iterate over fields in record layout, NFCI (#122029)

Move the common case of FieldDecl::getFieldIndex() inline to mitigate
the cost of removing the extra `FieldNo` induction variable.

Also rename isNoUniqueAddress parameter to isNonVirtualBaseType, which
appears to be more accurate. I think the current name is just a
consequence of autocomplete gone wrong.
This commit is contained in:
Reid Kleckner 2025-01-09 11:21:03 -08:00 committed by GitHub
parent 9ec92873ec
commit 26aa20a3dd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 52 additions and 59 deletions

View File

@ -3115,8 +3115,20 @@ public:
/// Returns the index of this field within its record,
/// as appropriate for passing to ASTRecordLayout::getFieldOffset.
unsigned getFieldIndex() const;
unsigned getFieldIndex() const {
const FieldDecl *Canonical = getCanonicalDecl();
if (Canonical->CachedFieldIndex == 0) {
Canonical->setCachedFieldIndex();
assert(Canonical->CachedFieldIndex != 0);
}
return Canonical->CachedFieldIndex - 1;
}
private:
/// Set CachedFieldIndex to the index of this field plus one.
void setCachedFieldIndex() const;
public:
/// Determines whether this field is mutable (C++ only).
bool isMutable() const { return Mutable; }

View File

@ -4651,12 +4651,9 @@ bool FieldDecl::isPotentiallyOverlapping() const {
return hasAttr<NoUniqueAddressAttr>() && getType()->getAsCXXRecordDecl();
}
unsigned FieldDecl::getFieldIndex() const {
const FieldDecl *Canonical = getCanonicalDecl();
if (Canonical != this)
return Canonical->getFieldIndex();
if (CachedFieldIndex) return CachedFieldIndex - 1;
void FieldDecl::setCachedFieldIndex() const {
assert(this == getCanonicalDecl() &&
"should be called on the canonical decl");
unsigned Index = 0;
const RecordDecl *RD = getParent()->getDefinition();
@ -4670,7 +4667,6 @@ unsigned FieldDecl::getFieldIndex() const {
}
assert(CachedFieldIndex && "failed to find field in parent");
return CachedFieldIndex - 1;
}
SourceRange FieldDecl::getSourceRange() const {

View File

@ -138,9 +138,9 @@ class EmptySubobjectMap {
return Offset <= MaxEmptyClassOffset;
}
CharUnits
getFieldOffset(const ASTRecordLayout &Layout, unsigned FieldNo) const {
uint64_t FieldOffset = Layout.getFieldOffset(FieldNo);
CharUnits getFieldOffset(const ASTRecordLayout &Layout,
const FieldDecl *Field) const {
uint64_t FieldOffset = Layout.getFieldOffset(Field->getFieldIndex());
assert(FieldOffset % CharWidth == 0 &&
"Field offset not at char boundary!");
@ -298,14 +298,12 @@ EmptySubobjectMap::CanPlaceBaseSubobjectAtOffset(const BaseSubobjectInfo *Info,
}
// Traverse all member variables.
unsigned FieldNo = 0;
for (CXXRecordDecl::field_iterator I = Info->Class->field_begin(),
E = Info->Class->field_end(); I != E; ++I, ++FieldNo) {
if (I->isBitField())
for (const FieldDecl *Field : Info->Class->fields()) {
if (Field->isBitField())
continue;
CharUnits FieldOffset = Offset + getFieldOffset(Layout, FieldNo);
if (!CanPlaceFieldSubobjectAtOffset(*I, FieldOffset))
CharUnits FieldOffset = Offset + getFieldOffset(Layout, Field);
if (!CanPlaceFieldSubobjectAtOffset(Field, FieldOffset))
return false;
}
@ -345,14 +343,12 @@ void EmptySubobjectMap::UpdateEmptyBaseSubobjects(const BaseSubobjectInfo *Info,
}
// Traverse all member variables.
unsigned FieldNo = 0;
for (CXXRecordDecl::field_iterator I = Info->Class->field_begin(),
E = Info->Class->field_end(); I != E; ++I, ++FieldNo) {
if (I->isBitField())
for (const FieldDecl *Field : Info->Class->fields()) {
if (Field->isBitField())
continue;
CharUnits FieldOffset = Offset + getFieldOffset(Layout, FieldNo);
UpdateEmptyFieldSubobjects(*I, FieldOffset, PlacingEmptyBase);
CharUnits FieldOffset = Offset + getFieldOffset(Layout, Field);
UpdateEmptyFieldSubobjects(Field, FieldOffset, PlacingEmptyBase);
}
}
@ -410,15 +406,12 @@ EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD,
}
// Traverse all member variables.
unsigned FieldNo = 0;
for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
I != E; ++I, ++FieldNo) {
if (I->isBitField())
for (const FieldDecl *Field : RD->fields()) {
if (Field->isBitField())
continue;
CharUnits FieldOffset = Offset + getFieldOffset(Layout, FieldNo);
if (!CanPlaceFieldSubobjectAtOffset(*I, FieldOffset))
CharUnits FieldOffset = Offset + getFieldOffset(Layout, Field);
if (!CanPlaceFieldSubobjectAtOffset(Field, FieldOffset))
return false;
}
@ -465,9 +458,8 @@ EmptySubobjectMap::CanPlaceFieldSubobjectAtOffset(const FieldDecl *FD,
return true;
}
bool
EmptySubobjectMap::CanPlaceFieldAtOffset(const FieldDecl *FD,
CharUnits Offset) {
bool EmptySubobjectMap::CanPlaceFieldAtOffset(const FieldDecl *FD,
CharUnits Offset) {
if (!CanPlaceFieldSubobjectAtOffset(FD, Offset))
return false;
@ -521,15 +513,12 @@ void EmptySubobjectMap::UpdateEmptyFieldSubobjects(
}
// Traverse all member variables.
unsigned FieldNo = 0;
for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
I != E; ++I, ++FieldNo) {
if (I->isBitField())
for (const FieldDecl *Field : RD->fields()) {
if (Field->isBitField())
continue;
CharUnits FieldOffset = Offset + getFieldOffset(Layout, FieldNo);
UpdateEmptyFieldSubobjects(*I, FieldOffset, PlacingOverlappingField);
CharUnits FieldOffset = Offset + getFieldOffset(Layout, Field);
UpdateEmptyFieldSubobjects(Field, FieldOffset, PlacingOverlappingField);
}
}
@ -1455,10 +1444,8 @@ void ItaniumRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
bool InsertExtraPadding = D->mayInsertExtraPadding(/*EmitRemark=*/true);
bool HasFlexibleArrayMember = D->hasFlexibleArrayMember();
for (auto I = D->field_begin(), End = D->field_end(); I != End; ++I) {
auto Next(I);
++Next;
LayoutField(*I,
InsertExtraPadding && (Next != End || !HasFlexibleArrayMember));
LayoutField(*I, InsertExtraPadding &&
(std::next(I) != End || !HasFlexibleArrayMember));
}
}
@ -3672,35 +3659,33 @@ static void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD,
}
// Dump fields.
uint64_t FieldNo = 0;
for (RecordDecl::field_iterator I = RD->field_begin(),
E = RD->field_end(); I != E; ++I, ++FieldNo) {
const FieldDecl &Field = **I;
uint64_t LocalFieldOffsetInBits = Layout.getFieldOffset(FieldNo);
for (const FieldDecl *Field : RD->fields()) {
uint64_t LocalFieldOffsetInBits =
Layout.getFieldOffset(Field->getFieldIndex());
CharUnits FieldOffset =
Offset + C.toCharUnitsFromBits(LocalFieldOffsetInBits);
// Recursively dump fields of record type.
if (auto RT = Field.getType()->getAs<RecordType>()) {
if (auto RT = Field->getType()->getAs<RecordType>()) {
DumpRecordLayout(OS, RT->getDecl(), C, FieldOffset, IndentLevel,
Field.getName().data(),
Field->getName().data(),
/*PrintSizeInfo=*/false,
/*IncludeVirtualBases=*/true);
continue;
}
if (Field.isBitField()) {
if (Field->isBitField()) {
uint64_t LocalFieldByteOffsetInBits = C.toBits(FieldOffset - Offset);
unsigned Begin = LocalFieldOffsetInBits - LocalFieldByteOffsetInBits;
unsigned Width = Field.getBitWidthValue(C);
unsigned Width = Field->getBitWidthValue(C);
PrintBitFieldOffset(OS, FieldOffset, Begin, Width, IndentLevel);
} else {
PrintOffset(OS, FieldOffset, IndentLevel);
}
const QualType &FieldType = C.getLangOpts().DumpRecordLayoutsCanonical
? Field.getType().getCanonicalType()
: Field.getType();
OS << FieldType << ' ' << Field << '\n';
? Field->getType().getCanonicalType()
: Field->getType();
OS << FieldType << ' ' << *Field << '\n';
}
// Dump virtual bases.

View File

@ -182,7 +182,7 @@ struct CGRecordLowering {
llvm::Type *StorageType);
/// Lowers an ASTRecordLayout to a llvm type.
void lower(bool NonVirtualBaseType);
void lowerUnion(bool isNoUniqueAddress);
void lowerUnion(bool isNonVirtualBaseType);
void accumulateFields(bool isNonVirtualBaseType);
RecordDecl::field_iterator
accumulateBitFields(bool isNonVirtualBaseType,
@ -310,9 +310,9 @@ void CGRecordLowering::lower(bool NVBaseType) {
computeVolatileBitfields();
}
void CGRecordLowering::lowerUnion(bool isNoUniqueAddress) {
void CGRecordLowering::lowerUnion(bool isNonVirtualBaseType) {
CharUnits LayoutSize =
isNoUniqueAddress ? Layout.getDataSize() : Layout.getSize();
isNonVirtualBaseType ? Layout.getDataSize() : Layout.getSize();
llvm::Type *StorageType = nullptr;
bool SeenNamedMember = false;
// Iterate through the fields setting bitFieldInfo and the Fields array. Also