@@ -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
148148struct 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
336336void 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
347347void 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
357357void 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
373377void 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
389385void 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
451442void 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
474461void 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
701680void 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
728700void AccessConflictAndMergeAnalysis::visitFullApply (FullApplySite fullApply,
@@ -737,33 +709,26 @@ void AccessConflictAndMergeAnalysis::visitFullApply(FullApplySite fullApply,
737709}
738710
739711void 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
769734void AccessConflictAndMergeAnalysis::visitMayRelease (SILInstruction *instr,
@@ -811,13 +776,12 @@ void AccessConflictAndMergeAnalysis::mergePredAccesses(
811776}
812777
813778void 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