@@ -63,6 +63,8 @@ struct OpenMPOpt {
63
63
64
64
// / Generic information that describes a runtime function
65
65
struct RuntimeFunctionInfo {
66
+ ~RuntimeFunctionInfo () { DeleteContainerSeconds (UsesMap); }
67
+
66
68
// / The kind, as described by the RuntimeFunction enum.
67
69
RuntimeFunction Kind;
68
70
@@ -82,7 +84,24 @@ struct OpenMPOpt {
82
84
Function *Declaration = nullptr ;
83
85
84
86
// / 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 (); }
86
105
87
106
// / Return the number of arguments (or the minimal number for variadic
88
107
// / functions).
@@ -92,16 +111,31 @@ struct OpenMPOpt {
92
111
// / true. The callback will be fed the function in which the use was
93
112
// / encountered as second argument.
94
113
void foreachUse (function_ref<bool (Use &, Function &)> CB) {
95
- SmallVector<Use * , 8 > ToBeDeleted;
114
+ SmallVector<unsigned , 8 > ToBeDeleted;
96
115
for (auto &It : UsesMap) {
97
116
ToBeDeleted.clear ();
98
- for (Use *U : It.second )
117
+ unsigned Idx = 0 ;
118
+ UseVector &UV = *It.second ;
119
+ for (Use *U : UV) {
99
120
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
+ }
103
132
}
104
133
}
134
+
135
+ private:
136
+ // / Map from functions to all uses of this runtime function contained in
137
+ // / them.
138
+ DenseMap<Function *, UseVector *> UsesMap;
105
139
};
106
140
107
141
// / Run all OpenMP optimizations on the underlying SCC/ModuleSlice.
@@ -248,15 +282,11 @@ struct OpenMPOpt {
248
282
// / \p ReplVal if given.
249
283
bool deduplicateRuntimeCalls (Function &F, RuntimeFunctionInfo &RFI,
250
284
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 )
253
287
return false ;
254
288
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 "
260
290
<< RFI.Name
261
291
<< (ReplVal ? " with an existing value\n " : " \n " )
262
292
<< " \n " );
@@ -278,7 +308,7 @@ struct OpenMPOpt {
278
308
};
279
309
280
310
if (!ReplVal) {
281
- for (Use *U : Uses )
311
+ for (Use *U : *UV )
282
312
if (CallInst *CI = getCallIfRegularCall (*U, &RFI)) {
283
313
if (!CanBeMoved (*CI))
284
314
continue ;
@@ -357,10 +387,11 @@ struct OpenMPOpt {
357
387
// The argument users of __kmpc_global_thread_num calls are GTIds.
358
388
RuntimeFunctionInfo &GlobThreadNumRFI =
359
389
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
+ });
364
395
365
396
// Transitively search for more arguments by looking at the users of the
366
397
// ones we know already. During the search the GTIdArgs vector is extended
@@ -432,11 +463,11 @@ struct OpenMPOpt {
432
463
for (Use &U : RFI.Declaration ->uses ()) {
433
464
if (Instruction *UserI = dyn_cast<Instruction>(U.getUser ())) {
434
465
if (ModuleSlice.count (UserI->getFunction ())) {
435
- RFI.UsesMap [ UserI->getFunction ()]. insert (&U);
466
+ RFI.getOrCreateUseVector ( UserI->getFunction ()). push_back (&U);
436
467
++NumUses;
437
468
}
438
469
} else {
439
- RFI.UsesMap [ nullptr ]. insert (&U);
470
+ RFI.getOrCreateUseVector ( nullptr ). push_back (&U);
440
471
++NumUses;
441
472
}
442
473
}
@@ -447,7 +478,7 @@ struct OpenMPOpt {
447
478
{ \
448
479
SmallVector<Type *, 8 > ArgsTypes ({__VA_ARGS__}); \
449
480
Function *F = M.getFunction (_Name); \
450
- if (declMatchesRTFTypes (F, _ReturnType , ArgsTypes)) { \
481
+ if (declMatchesRTFTypes (F, _ReturnType, ArgsTypes)) { \
451
482
auto &RFI = RFIs[_Enum]; \
452
483
RFI.Kind = _Enum; \
453
484
RFI.Name = _Name; \
@@ -459,10 +490,11 @@ struct OpenMPOpt {
459
490
(void )NumUses; \
460
491
LLVM_DEBUG ({ \
461
492
dbgs () << TAG << RFI.Name << (RFI.Declaration ? " " : " not" ) \
462
- << " found\n " ; \
493
+ << " found\n " ; \
463
494
if (RFI.Declaration ) \
464
495
dbgs () << TAG << " -> got " << NumUses << " uses in " \
465
- << RFI.UsesMap .size () << " different functions.\n " ; \
496
+ << RFI.getNumFunctionsWithUses () \
497
+ << " different functions.\n " ; \
466
498
}); \
467
499
} \
468
500
}
0 commit comments