Skip to content

Commit e4d951d

Browse files
authored
LowerTypeTests: Fix quadratic complexity.
Currently we have quadratic complexity in LowerTypeTests because ScopedSaveAliaseesAndUsed loops over all aliases for each disjoint set, and the number of aliases and number of disjoint sets is roughly proportional to the program size. Fix that by moving ScopedSaveAliaseesAndUsed to LowerTypeTestsModule::lower() so that we do this only once. Reviewers: fmayer, vitalybuka Reviewed By: vitalybuka Pull Request: llvm#135875
1 parent af63e1b commit e4d951d

File tree

1 file changed

+81
-83
lines changed

1 file changed

+81
-83
lines changed

llvm/lib/Transforms/IPO/LowerTypeTests.cpp

Lines changed: 81 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1669,61 +1669,55 @@ void LowerTypeTestsModule::buildBitSetsFromFunctionsNative(
16691669

16701670
lowerTypeTestCalls(TypeIds, JumpTable, GlobalLayout);
16711671

1672-
{
1673-
ScopedSaveAliaseesAndUsed S(M);
1672+
// Build aliases pointing to offsets into the jump table, and replace
1673+
// references to the original functions with references to the aliases.
1674+
for (unsigned I = 0; I != Functions.size(); ++I) {
1675+
Function *F = cast<Function>(Functions[I]->getGlobal());
1676+
bool IsJumpTableCanonical = Functions[I]->isJumpTableCanonical();
16741677

1675-
// Build aliases pointing to offsets into the jump table, and replace
1676-
// references to the original functions with references to the aliases.
1677-
for (unsigned I = 0; I != Functions.size(); ++I) {
1678-
Function *F = cast<Function>(Functions[I]->getGlobal());
1679-
bool IsJumpTableCanonical = Functions[I]->isJumpTableCanonical();
1680-
1681-
Constant *CombinedGlobalElemPtr = ConstantExpr::getInBoundsGetElementPtr(
1682-
JumpTableType, JumpTable,
1683-
ArrayRef<Constant *>{ConstantInt::get(IntPtrTy, 0),
1684-
ConstantInt::get(IntPtrTy, I)});
1685-
1686-
const bool IsExported = Functions[I]->isExported();
1687-
if (!IsJumpTableCanonical) {
1688-
GlobalValue::LinkageTypes LT = IsExported
1689-
? GlobalValue::ExternalLinkage
1690-
: GlobalValue::InternalLinkage;
1691-
GlobalAlias *JtAlias = GlobalAlias::create(F->getValueType(), 0, LT,
1692-
F->getName() + ".cfi_jt",
1693-
CombinedGlobalElemPtr, &M);
1694-
if (IsExported)
1695-
JtAlias->setVisibility(GlobalValue::HiddenVisibility);
1696-
else
1697-
appendToUsed(M, {JtAlias});
1698-
}
1678+
Constant *CombinedGlobalElemPtr = ConstantExpr::getInBoundsGetElementPtr(
1679+
JumpTableType, JumpTable,
1680+
ArrayRef<Constant *>{ConstantInt::get(IntPtrTy, 0),
1681+
ConstantInt::get(IntPtrTy, I)});
1682+
1683+
const bool IsExported = Functions[I]->isExported();
1684+
if (!IsJumpTableCanonical) {
1685+
GlobalValue::LinkageTypes LT = IsExported ? GlobalValue::ExternalLinkage
1686+
: GlobalValue::InternalLinkage;
1687+
GlobalAlias *JtAlias = GlobalAlias::create(F->getValueType(), 0, LT,
1688+
F->getName() + ".cfi_jt",
1689+
CombinedGlobalElemPtr, &M);
1690+
if (IsExported)
1691+
JtAlias->setVisibility(GlobalValue::HiddenVisibility);
1692+
else
1693+
appendToUsed(M, {JtAlias});
1694+
}
16991695

1700-
if (IsExported) {
1701-
if (IsJumpTableCanonical)
1702-
ExportSummary->cfiFunctionDefs().emplace(F->getName());
1703-
else
1704-
ExportSummary->cfiFunctionDecls().emplace(F->getName());
1705-
}
1696+
if (IsExported) {
1697+
if (IsJumpTableCanonical)
1698+
ExportSummary->cfiFunctionDefs().emplace(F->getName());
1699+
else
1700+
ExportSummary->cfiFunctionDecls().emplace(F->getName());
1701+
}
17061702

1707-
if (!IsJumpTableCanonical) {
1708-
if (F->hasExternalWeakLinkage())
1709-
replaceWeakDeclarationWithJumpTablePtr(F, CombinedGlobalElemPtr,
1710-
IsJumpTableCanonical);
1711-
else
1712-
replaceCfiUses(F, CombinedGlobalElemPtr, IsJumpTableCanonical);
1713-
} else {
1714-
assert(F->getType()->getAddressSpace() == 0);
1715-
1716-
GlobalAlias *FAlias =
1717-
GlobalAlias::create(F->getValueType(), 0, F->getLinkage(), "",
1718-
CombinedGlobalElemPtr, &M);
1719-
FAlias->setVisibility(F->getVisibility());
1720-
FAlias->takeName(F);
1721-
if (FAlias->hasName())
1722-
F->setName(FAlias->getName() + ".cfi");
1723-
replaceCfiUses(F, FAlias, IsJumpTableCanonical);
1724-
if (!F->hasLocalLinkage())
1725-
F->setVisibility(GlobalVariable::HiddenVisibility);
1726-
}
1703+
if (!IsJumpTableCanonical) {
1704+
if (F->hasExternalWeakLinkage())
1705+
replaceWeakDeclarationWithJumpTablePtr(F, CombinedGlobalElemPtr,
1706+
IsJumpTableCanonical);
1707+
else
1708+
replaceCfiUses(F, CombinedGlobalElemPtr, IsJumpTableCanonical);
1709+
} else {
1710+
assert(F->getType()->getAddressSpace() == 0);
1711+
1712+
GlobalAlias *FAlias = GlobalAlias::create(
1713+
F->getValueType(), 0, F->getLinkage(), "", CombinedGlobalElemPtr, &M);
1714+
FAlias->setVisibility(F->getVisibility());
1715+
FAlias->takeName(F);
1716+
if (FAlias->hasName())
1717+
F->setName(FAlias->getName() + ".cfi");
1718+
replaceCfiUses(F, FAlias, IsJumpTableCanonical);
1719+
if (!F->hasLocalLinkage())
1720+
F->setVisibility(GlobalVariable::HiddenVisibility);
17271721
}
17281722
}
17291723

@@ -2339,39 +2333,43 @@ bool LowerTypeTestsModule::lower() {
23392333
if (GlobalClasses.empty())
23402334
return false;
23412335

2342-
// For each disjoint set we found...
2343-
for (const auto &C : GlobalClasses) {
2344-
if (!C->isLeader())
2345-
continue;
2346-
2347-
++NumTypeIdDisjointSets;
2348-
// Build the list of type identifiers in this disjoint set.
2349-
std::vector<Metadata *> TypeIds;
2350-
std::vector<GlobalTypeMember *> Globals;
2351-
std::vector<ICallBranchFunnel *> ICallBranchFunnels;
2352-
for (auto M : GlobalClasses.members(*C)) {
2353-
if (isa<Metadata *>(M))
2354-
TypeIds.push_back(cast<Metadata *>(M));
2355-
else if (isa<GlobalTypeMember *>(M))
2356-
Globals.push_back(cast<GlobalTypeMember *>(M));
2357-
else
2358-
ICallBranchFunnels.push_back(cast<ICallBranchFunnel *>(M));
2359-
}
2360-
2361-
// Order type identifiers by unique ID for determinism. This ordering is
2362-
// stable as there is a one-to-one mapping between metadata and unique IDs.
2363-
llvm::sort(TypeIds, [&](Metadata *M1, Metadata *M2) {
2364-
return TypeIdInfo[M1].UniqueId < TypeIdInfo[M2].UniqueId;
2365-
});
2336+
{
2337+
ScopedSaveAliaseesAndUsed S(M);
2338+
// For each disjoint set we found...
2339+
for (const auto &C : GlobalClasses) {
2340+
if (!C->isLeader())
2341+
continue;
23662342

2367-
// Same for the branch funnels.
2368-
llvm::sort(ICallBranchFunnels,
2369-
[&](ICallBranchFunnel *F1, ICallBranchFunnel *F2) {
2370-
return F1->UniqueId < F2->UniqueId;
2371-
});
2343+
++NumTypeIdDisjointSets;
2344+
// Build the list of type identifiers in this disjoint set.
2345+
std::vector<Metadata *> TypeIds;
2346+
std::vector<GlobalTypeMember *> Globals;
2347+
std::vector<ICallBranchFunnel *> ICallBranchFunnels;
2348+
for (auto M : GlobalClasses.members(*C)) {
2349+
if (isa<Metadata *>(M))
2350+
TypeIds.push_back(cast<Metadata *>(M));
2351+
else if (isa<GlobalTypeMember *>(M))
2352+
Globals.push_back(cast<GlobalTypeMember *>(M));
2353+
else
2354+
ICallBranchFunnels.push_back(cast<ICallBranchFunnel *>(M));
2355+
}
23722356

2373-
// Build bitsets for this disjoint set.
2374-
buildBitSetsFromDisjointSet(TypeIds, Globals, ICallBranchFunnels);
2357+
// Order type identifiers by unique ID for determinism. This ordering is
2358+
// stable as there is a one-to-one mapping between metadata and unique
2359+
// IDs.
2360+
llvm::sort(TypeIds, [&](Metadata *M1, Metadata *M2) {
2361+
return TypeIdInfo[M1].UniqueId < TypeIdInfo[M2].UniqueId;
2362+
});
2363+
2364+
// Same for the branch funnels.
2365+
llvm::sort(ICallBranchFunnels,
2366+
[&](ICallBranchFunnel *F1, ICallBranchFunnel *F2) {
2367+
return F1->UniqueId < F2->UniqueId;
2368+
});
2369+
2370+
// Build bitsets for this disjoint set.
2371+
buildBitSetsFromDisjointSet(TypeIds, Globals, ICallBranchFunnels);
2372+
}
23752373
}
23762374

23772375
allocateByteArrays();

0 commit comments

Comments
 (0)