Skip to content

Commit 7297b81

Browse files
author
Joe Shajrawi
committed
AccessEnforcementOpts: Refactoring
1) use vectors instead of MapVector for in/out of scope local maps 2) record nested conflict without creating a temporary copy
1 parent c6a4e2c commit 7297b81

File tree

1 file changed

+97
-133
lines changed

1 file changed

+97
-133
lines changed

lib/SILOptimizer/Transforms/AccessEnforcementOpts.cpp

Lines changed: 97 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -142,13 +142,13 @@ namespace {
142142
/// Reachability results are stored here because very few accesses are
143143
/// typically in-progress at a particular program point,
144144
/// particularly at block boundaries.
145-
using DenseAccessMap = llvm::SmallMapVector<unsigned, BeginAccessInst *, 4>;
145+
using DenseAccessVec = llvm::SmallSetVector<BeginAccessInst *, 4>;
146146

147147
// Tracks the local data flow result for a basic block
148148
struct RegionInfo {
149149
struct AccessSummary {
150150
// The actual begin_access instructions
151-
DenseAccessMap conflictFreeAccesses;
151+
DenseAccessVec conflictFreeAccesses;
152152
// Flag to Indicate if we started a merging process
153153
bool merged;
154154
AccessSummary(unsigned size) : merged(false) {}
@@ -170,11 +170,11 @@ struct RegionInfo {
170170
unidentifiedAccess = false;
171171
}
172172

173-
const DenseAccessMap &getInScopeAccesses() {
173+
const DenseAccessVec &getInScopeAccesses() {
174174
return inScopeConflictFreeAccesses.conflictFreeAccesses;
175175
}
176176

177-
const DenseAccessMap &getOutOfScopeAccesses() {
177+
const DenseAccessVec &getOutOfScopeAccesses() {
178178
return outOfScopeConflictFreeAccesses.conflictFreeAccesses;
179179
}
180180
};
@@ -319,51 +319,55 @@ class AccessConflictAndMergeAnalysis {
319319
void merge(RegionInfo &info, const RegionInfo &RHS);
320320
void removeConflictFromStruct(RegionInfo &info,
321321
RegionInfo::AccessSummary &accessStruct,
322-
const AccessedStorage &storage);
322+
const AccessedStorage &storage, bool isInScope);
323323
void visitSetForConflicts(
324-
const DenseAccessMap &accessSet, RegionInfo &info,
324+
const DenseAccessVec &accessSet, RegionInfo &info,
325325
AccessConflictAndMergeAnalysis::AccessedStorageSet &loopStorage);
326326
void
327327
detectApplyConflicts(const swift::FunctionAccessedStorage &callSiteAccesses,
328-
const DenseAccessMap &conflictFreeSet,
328+
const DenseAccessVec &conflictFreeSet,
329329
const swift::FullApplySite &fullApply, RegionInfo &info);
330330

331-
void detectMayReleaseConflicts(const DenseAccessMap &conflictFreeSet,
331+
void detectMayReleaseConflicts(const DenseAccessVec &conflictFreeSet,
332332
SILInstruction *instr, RegionInfo &info);
333333
};
334334
} // namespace
335335

336336
void AccessConflictAndMergeAnalysis::addInScopeAccess(
337337
RegionInfo &info, BeginAccessInst *beginAccess) {
338-
auto &ai = result.getAccessInfo(beginAccess);
339-
auto index = ai.getAccessIndex();
340-
assert(info.getInScopeAccesses().find(index) ==
341-
info.inScopeConflictFreeAccesses.conflictFreeAccesses.end() &&
342-
"the begin_access should not have been in Set.");
343-
info.inScopeConflictFreeAccesses.conflictFreeAccesses.insert(
344-
std::make_pair(index, beginAccess));
338+
assert(
339+
std::find(info.inScopeConflictFreeAccesses.conflictFreeAccesses.begin(),
340+
info.inScopeConflictFreeAccesses.conflictFreeAccesses.end(),
341+
beginAccess) ==
342+
info.inScopeConflictFreeAccesses.conflictFreeAccesses.end() &&
343+
"the begin_access should not have been in Vec.");
344+
info.inScopeConflictFreeAccesses.conflictFreeAccesses.insert(beginAccess);
345345
}
346346

347347
void AccessConflictAndMergeAnalysis::removeInScopeAccess(
348348
RegionInfo &info, BeginAccessInst *beginAccess) {
349-
auto &ai = result.getAccessInfo(beginAccess);
350-
auto index = ai.getAccessIndex();
351-
auto it = info.inScopeConflictFreeAccesses.conflictFreeAccesses.find(index);
349+
auto it = std::find(
350+
info.inScopeConflictFreeAccesses.conflictFreeAccesses.begin(),
351+
info.inScopeConflictFreeAccesses.conflictFreeAccesses.end(), beginAccess);
352352
assert(it != info.inScopeConflictFreeAccesses.conflictFreeAccesses.end() &&
353-
"the begin_access should have been in Set.");
353+
"the begin_access should have been in Vec.");
354354
info.inScopeConflictFreeAccesses.conflictFreeAccesses.erase(it);
355355
}
356356

357357
void AccessConflictAndMergeAnalysis::removeConflictFromStruct(
358358
RegionInfo &info, RegionInfo::AccessSummary &accessStruct,
359-
const AccessedStorage &storage) {
360-
auto pred = [&](const std::pair<unsigned, BeginAccessInst *> &pair) {
361-
auto &currStorage = result.getAccessInfo(pair.second);
359+
const AccessedStorage &storage, bool isInScope) {
360+
auto pred = [&](BeginAccessInst *it) {
361+
auto &currStorage = result.getAccessInfo(it);
362362
return !currStorage.isDistinctFrom(storage);
363363
};
364364
auto it = std::find_if(accessStruct.conflictFreeAccesses.begin(),
365365
accessStruct.conflictFreeAccesses.end(), pred);
366366
while (it != accessStruct.conflictFreeAccesses.end()) {
367+
if (isInScope) {
368+
auto &ai = result.getAccessInfo(*it);
369+
ai.setSeenNestedConflict();
370+
}
367371
accessStruct.conflictFreeAccesses.erase(it);
368372
it = std::find_if(accessStruct.conflictFreeAccesses.begin(),
369373
accessStruct.conflictFreeAccesses.end(), pred);
@@ -372,26 +376,17 @@ void AccessConflictAndMergeAnalysis::removeConflictFromStruct(
372376

373377
void AccessConflictAndMergeAnalysis::recordConflict(
374378
RegionInfo &info, const AccessedStorage &storage) {
375-
removeConflictFromStruct(info, info.outOfScopeConflictFreeAccesses, storage);
376-
DenseAccessMap tmpSet(info.inScopeConflictFreeAccesses.conflictFreeAccesses);
377-
removeConflictFromStruct(info, info.inScopeConflictFreeAccesses, storage);
378-
for (auto it : tmpSet) {
379-
if (std::find(info.inScopeConflictFreeAccesses.conflictFreeAccesses.begin(),
380-
info.inScopeConflictFreeAccesses.conflictFreeAccesses.end(),
381-
it) ==
382-
info.inScopeConflictFreeAccesses.conflictFreeAccesses.end()) {
383-
auto &ai = result.getAccessInfo(it.second);
384-
ai.setSeenNestedConflict();
385-
}
386-
}
379+
removeConflictFromStruct(info, info.outOfScopeConflictFreeAccesses, storage,
380+
false /*isInScope*/);
381+
removeConflictFromStruct(info, info.inScopeConflictFreeAccesses, storage,
382+
true /*isInScope*/);
387383
}
388384

389385
void AccessConflictAndMergeAnalysis::addOutOfScopeAccess(
390386
RegionInfo &info, BeginAccessInst *beginAccess) {
391387
auto newStorageInfo = result.getAccessInfo(beginAccess);
392-
auto newIndex = newStorageInfo.getAccessIndex();
393-
auto pred = [&](const std::pair<unsigned, BeginAccessInst *> &pair) {
394-
auto currStorageInfo = result.getAccessInfo(pair.second);
388+
auto pred = [&](BeginAccessInst *it) {
389+
auto currStorageInfo = result.getAccessInfo(it);
395390
return currStorageInfo.hasIdenticalBase(newStorageInfo);
396391
};
397392

@@ -403,16 +398,19 @@ void AccessConflictAndMergeAnalysis::addOutOfScopeAccess(
403398
// We don't have a match in outOfScopeConflictFreeAccesses
404399
// Just add it and return
405400
info.outOfScopeConflictFreeAccesses.conflictFreeAccesses.insert(
406-
std::make_pair(newIndex, beginAccess));
401+
beginAccess);
407402
return;
408403
}
409404

410-
auto *otherBegin = it->second;
411-
auto index = it->first;
412-
info.outOfScopeConflictFreeAccesses.conflictFreeAccesses.erase(index);
405+
auto *otherBegin = *it;
406+
auto rmIt = std::find(
407+
info.outOfScopeConflictFreeAccesses.conflictFreeAccesses.begin(),
408+
info.outOfScopeConflictFreeAccesses.conflictFreeAccesses.end(),
409+
otherBegin);
410+
info.outOfScopeConflictFreeAccesses.conflictFreeAccesses.erase(rmIt);
413411

414-
auto predDistinct = [&](const std::pair<unsigned, BeginAccessInst *> &pair) {
415-
auto currStorageInfo = result.getAccessInfo(pair.second);
412+
auto predDistinct = [&](BeginAccessInst *it) {
413+
auto currStorageInfo = result.getAccessInfo(it);
416414
return !currStorageInfo.isDistinctFrom(newStorageInfo);
417415
};
418416

@@ -438,37 +436,26 @@ void AccessConflictAndMergeAnalysis::addOutOfScopeAccess(
438436
}
439437
}
440438

441-
info.outOfScopeConflictFreeAccesses.conflictFreeAccesses.insert(
442-
std::make_pair(newIndex, beginAccess));
443-
}
444-
445-
static void copyMap(DenseAccessMap &to, const DenseAccessMap &from) {
446-
for (auto it : from) {
447-
to.insert(it);
448-
}
439+
info.outOfScopeConflictFreeAccesses.conflictFreeAccesses.insert(beginAccess);
449440
}
450441

451442
void AccessConflictAndMergeAnalysis::mergeAccessStruct(
452443
RegionInfo &info, RegionInfo::AccessSummary &accessStruct,
453444
const RegionInfo::AccessSummary &RHSAccessStruct) {
454445
if (!accessStruct.merged) {
455-
copyMap(accessStruct.conflictFreeAccesses,
456-
RHSAccessStruct.conflictFreeAccesses);
446+
accessStruct.conflictFreeAccesses.insert(
447+
RHSAccessStruct.conflictFreeAccesses.begin(),
448+
RHSAccessStruct.conflictFreeAccesses.end());
457449
accessStruct.merged = true;
458450
return;
459451
}
460452

461-
DenseAccessMap tmpMap;
462-
copyMap(tmpMap, accessStruct.conflictFreeAccesses);
463-
464-
for (auto pair : tmpMap) {
465-
auto index = pair.first;
466-
if (RHSAccessStruct.conflictFreeAccesses.find(index) !=
467-
RHSAccessStruct.conflictFreeAccesses.end())
468-
continue;
469-
// Not in RHS - remove from intersect
470-
accessStruct.conflictFreeAccesses.erase(index);
471-
}
453+
auto pred = [&](BeginAccessInst *it) {
454+
auto rhsIt = std::find(RHSAccessStruct.conflictFreeAccesses.begin(),
455+
RHSAccessStruct.conflictFreeAccesses.end(), it);
456+
return rhsIt == RHSAccessStruct.conflictFreeAccesses.end();
457+
};
458+
accessStruct.conflictFreeAccesses.remove_if(pred);
472459
}
473460

474461
void AccessConflictAndMergeAnalysis::merge(RegionInfo &info,
@@ -643,31 +630,23 @@ void AccessConflictAndMergeAnalysis::visitBeginAccess(
643630
}
644631
SILAccessKind beginAccessKind = beginAccess->getAccessKind();
645632
// check the current in-scope accesses for conflicts:
646-
bool changed = false;
647-
do {
648-
changed = false;
649-
for (auto pair : info.getInScopeAccesses()) {
650-
auto *outerBeginAccess = pair.second;
651-
// If both are reads, keep the mapped access.
652-
if (!accessKindMayConflict(beginAccessKind,
653-
outerBeginAccess->getAccessKind())) {
654-
continue;
655-
}
633+
for (auto *outerBeginAccess : info.getInScopeAccesses()) {
634+
// If both are reads, keep the mapped access.
635+
if (!accessKindMayConflict(beginAccessKind,
636+
outerBeginAccess->getAccessKind())) {
637+
continue;
638+
}
656639

657-
auto &outerAccessInfo = result.getAccessInfo(outerBeginAccess);
658-
// If there is no potential conflict, leave the outer access mapped.
659-
if (!outerAccessInfo.isDistinctFrom(beginAccessInfo))
660-
continue;
640+
auto &outerAccessInfo = result.getAccessInfo(outerBeginAccess);
641+
// If there is no potential conflict, leave the outer access mapped.
642+
if (!outerAccessInfo.isDistinctFrom(beginAccessInfo))
643+
continue;
661644

662-
LLVM_DEBUG(beginAccessInfo.dump();
663-
llvm::dbgs() << " may conflict with:\n";
664-
outerAccessInfo.dump());
645+
LLVM_DEBUG(beginAccessInfo.dump(); llvm::dbgs() << " may conflict with:\n";
646+
outerAccessInfo.dump());
665647

666-
recordConflict(info, outerAccessInfo);
667-
changed = true;
668-
break;
669-
}
670-
} while (changed);
648+
recordConflict(info, outerAccessInfo);
649+
}
671650

672651
// Record the current access to InScopeAccesses.
673652
// It can potentially be folded
@@ -680,9 +659,9 @@ void AccessConflictAndMergeAnalysis::visitEndAccess(EndAccessInst *endAccess,
680659
auto *beginAccess = endAccess->getBeginAccess();
681660
if (beginAccess->getEnforcement() != SILAccessEnforcement::Dynamic)
682661
return;
683-
auto &ai = result.getAccessInfo(beginAccess);
684662
auto &inScope = info.getInScopeAccesses();
685-
if (inScope.find(ai.getAccessIndex()) != inScope.end()) {
663+
auto it = std::find(inScope.begin(), inScope.end(), beginAccess);
664+
if (it != inScope.end()) {
686665
LLVM_DEBUG(llvm::dbgs() << "No conflict on one path from " << *beginAccess
687666
<< " to " << *endAccess);
688667
removeInScopeAccess(info, beginAccess);
@@ -700,29 +679,22 @@ void AccessConflictAndMergeAnalysis::visitEndAccess(EndAccessInst *endAccess,
700679

701680
void AccessConflictAndMergeAnalysis::detectApplyConflicts(
702681
const swift::FunctionAccessedStorage &callSiteAccesses,
703-
const DenseAccessMap &conflictFreeSet,
682+
const DenseAccessVec &conflictFreeSet,
704683
const swift::FullApplySite &fullApply, RegionInfo &info) {
705-
bool changed = false;
706-
do {
707-
changed = false;
708-
for (auto pair : conflictFreeSet) {
709-
auto *outerBeginAccess = pair.second;
710-
// If there is no potential conflict, leave the outer access mapped.
711-
SILAccessKind accessKind = outerBeginAccess->getAccessKind();
712-
AccessInfo &outerAccessInfo = result.getAccessInfo(outerBeginAccess);
713-
if (!callSiteAccesses.mayConflictWith(accessKind, outerAccessInfo))
714-
continue;
684+
for (auto *outerBeginAccess : conflictFreeSet) {
685+
// If there is no potential conflict, leave the outer access mapped.
686+
SILAccessKind accessKind = outerBeginAccess->getAccessKind();
687+
AccessInfo &outerAccessInfo = result.getAccessInfo(outerBeginAccess);
688+
if (!callSiteAccesses.mayConflictWith(accessKind, outerAccessInfo))
689+
continue;
715690

716-
LLVM_DEBUG(
717-
llvm::dbgs() << *fullApply.getInstruction() << " call site access: ";
718-
callSiteAccesses.dump(); llvm::dbgs() << " may conflict with:\n";
719-
outerAccessInfo.dump());
691+
LLVM_DEBUG(
692+
llvm::dbgs() << *fullApply.getInstruction() << " call site access: ";
693+
callSiteAccesses.dump(); llvm::dbgs() << " may conflict with:\n";
694+
outerAccessInfo.dump());
720695

721-
recordConflict(info, outerAccessInfo);
722-
changed = true;
723-
break;
724-
}
725-
} while (changed);
696+
recordConflict(info, outerAccessInfo);
697+
}
726698
}
727699

728700
void AccessConflictAndMergeAnalysis::visitFullApply(FullApplySite fullApply,
@@ -737,33 +709,26 @@ void AccessConflictAndMergeAnalysis::visitFullApply(FullApplySite fullApply,
737709
}
738710

739711
void AccessConflictAndMergeAnalysis::detectMayReleaseConflicts(
740-
const DenseAccessMap &conflictFreeSet, SILInstruction *instr,
712+
const DenseAccessVec &conflictFreeSet, SILInstruction *instr,
741713
RegionInfo &info) {
742714
// TODO Introduce "Pure Swift" deinitializers
743715
// We can then make use of alias information for instr's operands
744716
// If they don't alias - we might get away with not recording a conflict
745-
bool changed = false;
746-
do {
747-
changed = false;
748-
for (auto pair : conflictFreeSet) {
749-
auto *outerBeginAccess = pair.second;
750-
// Only class and global access that may alias would conflict
751-
AccessInfo &outerAccessInfo = result.getAccessInfo(outerBeginAccess);
752-
const AccessedStorage::Kind outerKind = outerAccessInfo.getKind();
753-
if (outerKind != AccessedStorage::Class &&
754-
outerKind != AccessedStorage::Global) {
755-
continue;
756-
}
757-
// We can't prove what the deinitializer might do
758-
// TODO Introduce "Pure Swift" deinitializers
759-
LLVM_DEBUG(llvm::dbgs() << "MayRelease Instruction: " << *instr
760-
<< " may conflict with:\n";
761-
outerAccessInfo.dump());
762-
recordConflict(info, outerAccessInfo);
763-
changed = true;
764-
break;
717+
for (auto *outerBeginAccess : conflictFreeSet) {
718+
// Only class and global access that may alias would conflict
719+
AccessInfo &outerAccessInfo = result.getAccessInfo(outerBeginAccess);
720+
const AccessedStorage::Kind outerKind = outerAccessInfo.getKind();
721+
if (outerKind != AccessedStorage::Class &&
722+
outerKind != AccessedStorage::Global) {
723+
continue;
765724
}
766-
} while (changed);
725+
// We can't prove what the deinitializer might do
726+
// TODO Introduce "Pure Swift" deinitializers
727+
LLVM_DEBUG(llvm::dbgs() << "MayRelease Instruction: " << *instr
728+
<< " may conflict with:\n";
729+
outerAccessInfo.dump());
730+
recordConflict(info, outerAccessInfo);
731+
}
767732
}
768733

769734
void AccessConflictAndMergeAnalysis::visitMayRelease(SILInstruction *instr,
@@ -811,13 +776,12 @@ void AccessConflictAndMergeAnalysis::mergePredAccesses(
811776
}
812777

813778
void AccessConflictAndMergeAnalysis::visitSetForConflicts(
814-
const DenseAccessMap &accessSet, RegionInfo &info,
779+
const DenseAccessVec &accessSet, RegionInfo &info,
815780
AccessConflictAndMergeAnalysis::AccessedStorageSet &loopStorage) {
816781
bool changed = false;
817782
do {
818783
changed = false;
819-
for (auto pair : accessSet) {
820-
BeginAccessInst *beginAccess = pair.second;
784+
for (BeginAccessInst *beginAccess : accessSet) {
821785
AccessInfo &accessInfo = result.getAccessInfo(beginAccess);
822786

823787
for (auto loopAccess : loopStorage) {

0 commit comments

Comments
 (0)