Skip to content

Commit 79012fc

Browse files
authored
[LowerTypeTests] Optimize buildBitSet (llvm#157386)
`buildBitSet` had a loop trough entire GlobalLayout to pickup matching offsets. The patch maps all offsets to correspondign `TypeId`, so we pass prepared list of offsets into `buildBitSet`. On one large internal binary, `LowerTypeTests` took 58% of ThinLTO link time before the patch. After the patch just 7% (absolute saving is 200s).
1 parent d8f0a57 commit 79012fc

File tree

3 files changed

+43
-40
lines changed

3 files changed

+43
-40
lines changed

llvm/include/llvm/Transforms/IPO/LowerTypeTests.h

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,12 @@ struct BitSetBuilder {
6464
uint64_t Min = std::numeric_limits<uint64_t>::max();
6565
uint64_t Max = 0;
6666

67-
BitSetBuilder() = default;
68-
69-
void addOffset(uint64_t Offset) {
70-
if (Min > Offset)
71-
Min = Offset;
72-
if (Max < Offset)
73-
Max = Offset;
74-
75-
Offsets.push_back(Offset);
67+
explicit BitSetBuilder(ArrayRef<uint64_t> Offsets) : Offsets(Offsets) {
68+
if (!Offsets.empty()) {
69+
auto [MinIt, MaxIt] = std::minmax_element(Offsets.begin(), Offsets.end());
70+
Min = *MinIt;
71+
Max = *MaxIt;
72+
}
7673
}
7774

7875
LLVM_ABI BitSetInfo build();

llvm/lib/Transforms/IPO/LowerTypeTests.cpp

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -573,28 +573,11 @@ class LowerTypeTestsModule {
573573
};
574574
} // end anonymous namespace
575575

576-
/// Build a bit set for TypeId using the object layouts in
577-
/// GlobalLayout.
578-
static BitSetInfo
579-
buildBitSet(Metadata *TypeId,
580-
const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout) {
581-
BitSetBuilder BSB;
582-
576+
/// Build a bit set for list of offsets.
577+
static BitSetInfo buildBitSet(ArrayRef<uint64_t> Offsets) {
583578
// Compute the byte offset of each address associated with this type
584579
// identifier.
585-
for (const auto &GlobalAndOffset : GlobalLayout) {
586-
for (MDNode *Type : GlobalAndOffset.first->types()) {
587-
if (Type->getOperand(1) != TypeId)
588-
continue;
589-
uint64_t Offset =
590-
cast<ConstantInt>(
591-
cast<ConstantAsMetadata>(Type->getOperand(0))->getValue())
592-
->getZExtValue();
593-
BSB.addOffset(GlobalAndOffset.second + Offset);
594-
}
595-
}
596-
597-
return BSB.build();
580+
return BitSetBuilder(Offsets).build();
598581
}
599582

600583
/// Build a test that bit BitOffset mod sizeof(Bits)*8 is set in
@@ -1161,21 +1144,47 @@ void LowerTypeTestsModule::importFunction(Function *F,
11611144
F->setVisibility(Visibility);
11621145
}
11631146

1164-
void LowerTypeTestsModule::lowerTypeTestCalls(
1165-
ArrayRef<Metadata *> TypeIds, Constant *CombinedGlobalAddr,
1166-
const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout) {
1167-
// For each type identifier in this disjoint set...
1147+
static auto
1148+
buildBitSets(ArrayRef<Metadata *> TypeIds,
1149+
const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout) {
1150+
DenseMap<Metadata *, SmallVector<uint64_t, 16>> OffsetsByTypeID;
1151+
// Pre-populate the map with interesting type identifiers.
1152+
for (Metadata *TypeId : TypeIds)
1153+
OffsetsByTypeID[TypeId];
1154+
for (const auto &[Mem, MemOff] : GlobalLayout) {
1155+
for (MDNode *Type : Mem->types()) {
1156+
auto It = OffsetsByTypeID.find(Type->getOperand(1));
1157+
if (It == OffsetsByTypeID.end())
1158+
continue;
1159+
uint64_t Offset =
1160+
cast<ConstantInt>(
1161+
cast<ConstantAsMetadata>(Type->getOperand(0))->getValue())
1162+
->getZExtValue();
1163+
It->second.push_back(MemOff + Offset);
1164+
}
1165+
}
1166+
1167+
SmallVector<std::pair<Metadata *, BitSetInfo>> BitSets;
1168+
BitSets.reserve(TypeIds.size());
11681169
for (Metadata *TypeId : TypeIds) {
1169-
// Build the bitset.
1170-
BitSetInfo BSI = buildBitSet(TypeId, GlobalLayout);
1170+
BitSets.emplace_back(TypeId, buildBitSet(OffsetsByTypeID[TypeId]));
11711171
LLVM_DEBUG({
11721172
if (auto MDS = dyn_cast<MDString>(TypeId))
11731173
dbgs() << MDS->getString() << ": ";
11741174
else
11751175
dbgs() << "<unnamed>: ";
1176-
BSI.print(dbgs());
1176+
BitSets.back().second.print(dbgs());
11771177
});
1178+
}
1179+
1180+
return BitSets;
1181+
}
11781182

1183+
void LowerTypeTestsModule::lowerTypeTestCalls(
1184+
ArrayRef<Metadata *> TypeIds, Constant *CombinedGlobalAddr,
1185+
const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout) {
1186+
// For each type identifier in this disjoint set...
1187+
for (const auto &[TypeId, BSI] : buildBitSets(TypeIds, GlobalLayout)) {
11791188
ByteArrayInfo *BAI = nullptr;
11801189
TypeIdLowering TIL;
11811190

llvm/unittests/Transforms/IPO/LowerTypeTests.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,7 @@ TEST(LowerTypeTests, BitSetBuilder) {
5151
};
5252

5353
for (auto &&T : BSBTests) {
54-
BitSetBuilder BSB;
55-
for (auto Offset : T.Offsets)
56-
BSB.addOffset(Offset);
57-
54+
BitSetBuilder BSB(T.Offsets);
5855
BitSetInfo BSI = BSB.build();
5956

6057
EXPECT_EQ(T.Bits, BSI.Bits);

0 commit comments

Comments
 (0)