Skip to content

Commit 8855fec

Browse files
committed
[OpenMPOpt] Use a pointer value type in map
The value type was a set before which can easily lead to excessive memory usage and copying. We use a pointer to a vector instead now.
1 parent ee17263 commit 8855fec

File tree

1 file changed

+55
-23
lines changed

1 file changed

+55
-23
lines changed

llvm/lib/Transforms/IPO/OpenMPOpt.cpp

Lines changed: 55 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ struct OpenMPOpt {
6363

6464
/// Generic information that describes a runtime function
6565
struct RuntimeFunctionInfo {
66+
~RuntimeFunctionInfo() { DeleteContainerSeconds(UsesMap); }
67+
6668
/// The kind, as described by the RuntimeFunction enum.
6769
RuntimeFunction Kind;
6870

@@ -82,7 +84,24 @@ struct OpenMPOpt {
8284
Function *Declaration = nullptr;
8385

8486
/// Uses of this runtime function per function containing the use.
85-
DenseMap<Function *, SmallPtrSet<Use *, 16>> UsesMap;
87+
using UseVector = SmallVector<Use *, 16>;
88+
89+
/// Return the vector of uses in function \p F.
90+
UseVector &getOrCreateUseVector(Function *F) {
91+
UseVector *&UV = UsesMap[F];
92+
if (!UV)
93+
UV = new UseVector();
94+
return *UV;
95+
}
96+
97+
/// Return the vector of uses in function \p F or `nullptr` if there are
98+
/// none.
99+
const UseVector *getUseVector(Function &F) const {
100+
return UsesMap.lookup(&F);
101+
}
102+
103+
/// Return how many functions contain uses of this runtime function.
104+
size_t getNumFunctionsWithUses() const { return UsesMap.size(); }
86105

87106
/// Return the number of arguments (or the minimal number for variadic
88107
/// functions).
@@ -92,16 +111,31 @@ struct OpenMPOpt {
92111
/// true. The callback will be fed the function in which the use was
93112
/// encountered as second argument.
94113
void foreachUse(function_ref<bool(Use &, Function &)> CB) {
95-
SmallVector<Use *, 8> ToBeDeleted;
114+
SmallVector<unsigned, 8> ToBeDeleted;
96115
for (auto &It : UsesMap) {
97116
ToBeDeleted.clear();
98-
for (Use *U : It.second)
117+
unsigned Idx = 0;
118+
UseVector &UV = *It.second;
119+
for (Use *U : UV) {
99120
if (CB(*U, *It.first))
100-
ToBeDeleted.push_back(U);
101-
for (Use *U : ToBeDeleted)
102-
It.second.erase(U);
121+
ToBeDeleted.push_back(Idx);
122+
++Idx;
123+
}
124+
125+
// Remove the to-be-deleted indices in reverse order as prior
126+
// modifcations will not modify the smaller indices.
127+
while (!ToBeDeleted.empty()) {
128+
unsigned Idx = ToBeDeleted.pop_back_val();
129+
UV[Idx] = UV.back();
130+
UV.pop_back();
131+
}
103132
}
104133
}
134+
135+
private:
136+
/// Map from functions to all uses of this runtime function contained in
137+
/// them.
138+
DenseMap<Function *, UseVector *> UsesMap;
105139
};
106140

107141
/// Run all OpenMP optimizations on the underlying SCC/ModuleSlice.
@@ -248,15 +282,11 @@ struct OpenMPOpt {
248282
/// \p ReplVal if given.
249283
bool deduplicateRuntimeCalls(Function &F, RuntimeFunctionInfo &RFI,
250284
Value *ReplVal = nullptr) {
251-
auto UsesIt = RFI.UsesMap.find(&F);
252-
if (UsesIt == RFI.UsesMap.end())
285+
auto *UV = RFI.getUseVector(F);
286+
if (!UV || UV->size() + (ReplVal != nullptr) < 2)
253287
return false;
254288

255-
auto &Uses = UsesIt->getSecond();
256-
if (Uses.size() + (ReplVal != nullptr) < 2)
257-
return false;
258-
259-
LLVM_DEBUG(dbgs() << TAG << "Deduplicate " << Uses.size() << " uses of "
289+
LLVM_DEBUG(dbgs() << TAG << "Deduplicate " << UV->size() << " uses of "
260290
<< RFI.Name
261291
<< (ReplVal ? " with an existing value\n" : "\n")
262292
<< "\n");
@@ -278,7 +308,7 @@ struct OpenMPOpt {
278308
};
279309

280310
if (!ReplVal) {
281-
for (Use *U : Uses)
311+
for (Use *U : *UV)
282312
if (CallInst *CI = getCallIfRegularCall(*U, &RFI)) {
283313
if (!CanBeMoved(*CI))
284314
continue;
@@ -357,10 +387,11 @@ struct OpenMPOpt {
357387
// The argument users of __kmpc_global_thread_num calls are GTIds.
358388
RuntimeFunctionInfo &GlobThreadNumRFI =
359389
RFIs[OMPRTL___kmpc_global_thread_num];
360-
for (auto &It : GlobThreadNumRFI.UsesMap)
361-
for (Use *U : It.second)
362-
if (CallInst *CI = getCallIfRegularCall(*U, &GlobThreadNumRFI))
363-
AddUserArgs(*CI);
390+
GlobThreadNumRFI.foreachUse([&](Use &U, Function &F) {
391+
if (CallInst *CI = getCallIfRegularCall(U, &GlobThreadNumRFI))
392+
AddUserArgs(*CI);
393+
return false;
394+
});
364395

365396
// Transitively search for more arguments by looking at the users of the
366397
// ones we know already. During the search the GTIdArgs vector is extended
@@ -432,11 +463,11 @@ struct OpenMPOpt {
432463
for (Use &U : RFI.Declaration->uses()) {
433464
if (Instruction *UserI = dyn_cast<Instruction>(U.getUser())) {
434465
if (ModuleSlice.count(UserI->getFunction())) {
435-
RFI.UsesMap[UserI->getFunction()].insert(&U);
466+
RFI.getOrCreateUseVector(UserI->getFunction()).push_back(&U);
436467
++NumUses;
437468
}
438469
} else {
439-
RFI.UsesMap[nullptr].insert(&U);
470+
RFI.getOrCreateUseVector(nullptr).push_back(&U);
440471
++NumUses;
441472
}
442473
}
@@ -447,7 +478,7 @@ struct OpenMPOpt {
447478
{ \
448479
SmallVector<Type *, 8> ArgsTypes({__VA_ARGS__}); \
449480
Function *F = M.getFunction(_Name); \
450-
if (declMatchesRTFTypes(F, _ReturnType , ArgsTypes)) { \
481+
if (declMatchesRTFTypes(F, _ReturnType, ArgsTypes)) { \
451482
auto &RFI = RFIs[_Enum]; \
452483
RFI.Kind = _Enum; \
453484
RFI.Name = _Name; \
@@ -459,10 +490,11 @@ struct OpenMPOpt {
459490
(void)NumUses; \
460491
LLVM_DEBUG({ \
461492
dbgs() << TAG << RFI.Name << (RFI.Declaration ? "" : " not") \
462-
<< " found\n"; \
493+
<< " found\n"; \
463494
if (RFI.Declaration) \
464495
dbgs() << TAG << "-> got " << NumUses << " uses in " \
465-
<< RFI.UsesMap.size() << " different functions.\n"; \
496+
<< RFI.getNumFunctionsWithUses() \
497+
<< " different functions.\n"; \
466498
}); \
467499
} \
468500
}

0 commit comments

Comments
 (0)