diff --git a/llvm/include/llvm/Transforms/IPO/LowerTypeTests.h b/llvm/include/llvm/Transforms/IPO/LowerTypeTests.h index 253d13f81857b..a34cbaf72675b 100644 --- a/llvm/include/llvm/Transforms/IPO/LowerTypeTests.h +++ b/llvm/include/llvm/Transforms/IPO/LowerTypeTests.h @@ -64,15 +64,12 @@ struct BitSetBuilder { uint64_t Min = std::numeric_limits::max(); uint64_t Max = 0; - BitSetBuilder() = default; - - void addOffset(uint64_t Offset) { - if (Min > Offset) - Min = Offset; - if (Max < Offset) - Max = Offset; - - Offsets.push_back(Offset); + explicit BitSetBuilder(ArrayRef Offsets) : Offsets(Offsets) { + if (!Offsets.empty()) { + auto [MinIt, MaxIt] = std::minmax_element(Offsets.begin(), Offsets.end()); + Min = *MinIt; + Max = *MaxIt; + } } LLVM_ABI BitSetInfo build(); diff --git a/llvm/lib/Transforms/IPO/LowerTypeTests.cpp b/llvm/lib/Transforms/IPO/LowerTypeTests.cpp index 821a9d82ddb0d..be6cba38d8b3c 100644 --- a/llvm/lib/Transforms/IPO/LowerTypeTests.cpp +++ b/llvm/lib/Transforms/IPO/LowerTypeTests.cpp @@ -573,28 +573,11 @@ class LowerTypeTestsModule { }; } // end anonymous namespace -/// Build a bit set for TypeId using the object layouts in -/// GlobalLayout. -static BitSetInfo -buildBitSet(Metadata *TypeId, - const DenseMap &GlobalLayout) { - BitSetBuilder BSB; - +/// Build a bit set for list of offsets. +static BitSetInfo buildBitSet(ArrayRef Offsets) { // Compute the byte offset of each address associated with this type // identifier. - for (const auto &GlobalAndOffset : GlobalLayout) { - for (MDNode *Type : GlobalAndOffset.first->types()) { - if (Type->getOperand(1) != TypeId) - continue; - uint64_t Offset = - cast( - cast(Type->getOperand(0))->getValue()) - ->getZExtValue(); - BSB.addOffset(GlobalAndOffset.second + Offset); - } - } - - return BSB.build(); + return BitSetBuilder(Offsets).build(); } /// Build a test that bit BitOffset mod sizeof(Bits)*8 is set in @@ -1161,21 +1144,47 @@ void LowerTypeTestsModule::importFunction(Function *F, F->setVisibility(Visibility); } -void LowerTypeTestsModule::lowerTypeTestCalls( - ArrayRef TypeIds, Constant *CombinedGlobalAddr, - const DenseMap &GlobalLayout) { - // For each type identifier in this disjoint set... +static auto +buildBitSets(ArrayRef TypeIds, + const DenseMap &GlobalLayout) { + DenseMap> OffsetsByTypeID; + // Pre-populate the map with interesting type identifiers. + for (Metadata *TypeId : TypeIds) + OffsetsByTypeID[TypeId]; + for (const auto &[Mem, MemOff] : GlobalLayout) { + for (MDNode *Type : Mem->types()) { + auto It = OffsetsByTypeID.find(Type->getOperand(1)); + if (It == OffsetsByTypeID.end()) + continue; + uint64_t Offset = + cast( + cast(Type->getOperand(0))->getValue()) + ->getZExtValue(); + It->second.push_back(MemOff + Offset); + } + } + + SmallVector> BitSets; + BitSets.reserve(TypeIds.size()); for (Metadata *TypeId : TypeIds) { - // Build the bitset. - BitSetInfo BSI = buildBitSet(TypeId, GlobalLayout); + BitSets.emplace_back(TypeId, buildBitSet(OffsetsByTypeID[TypeId])); LLVM_DEBUG({ if (auto MDS = dyn_cast(TypeId)) dbgs() << MDS->getString() << ": "; else dbgs() << ": "; - BSI.print(dbgs()); + BitSets.back().second.print(dbgs()); }); + } + + return BitSets; +} +void LowerTypeTestsModule::lowerTypeTestCalls( + ArrayRef TypeIds, Constant *CombinedGlobalAddr, + const DenseMap &GlobalLayout) { + // For each type identifier in this disjoint set... + for (const auto &[TypeId, BSI] : buildBitSets(TypeIds, GlobalLayout)) { ByteArrayInfo *BAI = nullptr; TypeIdLowering TIL; diff --git a/llvm/unittests/Transforms/IPO/LowerTypeTests.cpp b/llvm/unittests/Transforms/IPO/LowerTypeTests.cpp index fc41b036ffb6c..3d6b7efbccd91 100644 --- a/llvm/unittests/Transforms/IPO/LowerTypeTests.cpp +++ b/llvm/unittests/Transforms/IPO/LowerTypeTests.cpp @@ -51,10 +51,7 @@ TEST(LowerTypeTests, BitSetBuilder) { }; for (auto &&T : BSBTests) { - BitSetBuilder BSB; - for (auto Offset : T.Offsets) - BSB.addOffset(Offset); - + BitSetBuilder BSB(T.Offsets); BitSetInfo BSI = BSB.build(); EXPECT_EQ(T.Bits, BSI.Bits);