Skip to content

Commit aa70e1b

Browse files
author
Joe Shajrawi
authored
Merge pull request #22833 from shajrawi/access_opts_assert
AccessEnforcementOpts: Fix a bug that caused a compiler assert when dealing with nested scopes
2 parents 84fbd02 + a4f7d01 commit aa70e1b

File tree

2 files changed

+107
-13
lines changed

2 files changed

+107
-13
lines changed

lib/SILOptimizer/Transforms/AccessEnforcementOpts.cpp

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,9 @@ class AccessConflictAndMergeAnalysis {
319319
void addInScopeAccess(RegionInfo &info, BeginAccessInst *beginAccess);
320320
void removeInScopeAccess(RegionInfo &info, BeginAccessInst *beginAccess);
321321
void recordConflict(RegionInfo &info, const AccessedStorage &storage);
322-
void addOutOfScopeAccess(RegionInfo &info, BeginAccessInst *beginAccess);
322+
void addOutOfScopeAccessInsert(RegionInfo &info,
323+
BeginAccessInst *beginAccess);
324+
void addOutOfScopeAccessMerge(RegionInfo &info, BeginAccessInst *beginAccess);
323325
void mergeAccessStruct(RegionInfo &info,
324326
RegionInfo::AccessSummary &accessStruct,
325327
const RegionInfo::AccessSummary &RHSAccessStruct);
@@ -386,7 +388,7 @@ void AccessConflictAndMergeAnalysis::recordConflict(
386388
true /*isInScope*/);
387389
}
388390

389-
void AccessConflictAndMergeAnalysis::addOutOfScopeAccess(
391+
void AccessConflictAndMergeAnalysis::addOutOfScopeAccessInsert(
390392
RegionInfo &info, BeginAccessInst *beginAccess) {
391393
auto newStorageInfo = result.getAccessInfo(beginAccess);
392394
auto pred = [&](BeginAccessInst *it) {
@@ -399,10 +401,42 @@ void AccessConflictAndMergeAnalysis::addOutOfScopeAccess(
399401
info.outOfScopeConflictFreeAccesses.conflictFreeAccesses.rend(), pred);
400402

401403
if (it == info.outOfScopeConflictFreeAccesses.conflictFreeAccesses.rend()) {
402-
// We don't have a match in outOfScopeConflictFreeAccesses
403-
// Just add it and return
404404
info.outOfScopeConflictFreeAccesses.conflictFreeAccesses.insert(
405405
beginAccess);
406+
} else {
407+
// we have a nested read case:
408+
/*%4 = begin_access [read] [dynamic] %0 : $*X
409+
%5 = load %4 : $*X
410+
%7 = begin_access [read] [dynamic] %0 : $*X
411+
%8 = load %7 : $*X
412+
end_access %7 : $*X
413+
end_access %4 : $*X*/
414+
// we should remove the current one and insert the new.
415+
auto *otherBegin = *it;
416+
auto rmIt = std::find(
417+
info.outOfScopeConflictFreeAccesses.conflictFreeAccesses.begin(),
418+
info.outOfScopeConflictFreeAccesses.conflictFreeAccesses.end(),
419+
otherBegin);
420+
info.outOfScopeConflictFreeAccesses.conflictFreeAccesses.erase(rmIt);
421+
info.outOfScopeConflictFreeAccesses.conflictFreeAccesses.insert(
422+
beginAccess);
423+
}
424+
}
425+
426+
void AccessConflictAndMergeAnalysis::addOutOfScopeAccessMerge(
427+
RegionInfo &info, BeginAccessInst *beginAccess) {
428+
auto newStorageInfo = result.getAccessInfo(beginAccess);
429+
auto pred = [&](BeginAccessInst *it) {
430+
auto currStorageInfo = result.getAccessInfo(it);
431+
return currStorageInfo.hasIdenticalBase(newStorageInfo);
432+
};
433+
434+
auto it = std::find_if(
435+
info.outOfScopeConflictFreeAccesses.conflictFreeAccesses.rbegin(),
436+
info.outOfScopeConflictFreeAccesses.conflictFreeAccesses.rend(), pred);
437+
438+
if (it == info.outOfScopeConflictFreeAccesses.conflictFreeAccesses.rend()) {
439+
// We don't have a match in outOfScopeConflictFreeAccesses - return
406440
return;
407441
}
408442

@@ -418,29 +452,27 @@ void AccessConflictAndMergeAnalysis::addOutOfScopeAccess(
418452
return !currStorageInfo.isDistinctFrom(newStorageInfo);
419453
};
420454

421-
auto itDistinct = std::find_if(
455+
auto itNotDistinct = std::find_if(
422456
info.outOfScopeConflictFreeAccesses.conflictFreeAccesses.begin(),
423457
info.outOfScopeConflictFreeAccesses.conflictFreeAccesses.end(),
424458
predDistinct);
425459

426-
if (itDistinct ==
460+
if (itNotDistinct ==
427461
info.outOfScopeConflictFreeAccesses.conflictFreeAccesses.end()) {
428462
LLVM_DEBUG(llvm::dbgs() << "Found mergable pair: " << *otherBegin << ", "
429463
<< *beginAccess << "\n");
430464
result.mergePairs.push_back(std::make_pair(otherBegin, beginAccess));
431465
} else {
432-
while (itDistinct !=
466+
while (itNotDistinct !=
433467
info.outOfScopeConflictFreeAccesses.conflictFreeAccesses.end()) {
434468
info.outOfScopeConflictFreeAccesses.conflictFreeAccesses.erase(
435-
itDistinct);
436-
itDistinct = std::find_if(
469+
itNotDistinct);
470+
itNotDistinct = std::find_if(
437471
info.outOfScopeConflictFreeAccesses.conflictFreeAccesses.begin(),
438472
info.outOfScopeConflictFreeAccesses.conflictFreeAccesses.end(),
439473
predDistinct);
440474
}
441475
}
442-
443-
info.outOfScopeConflictFreeAccesses.conflictFreeAccesses.insert(beginAccess);
444476
}
445477

446478
void AccessConflictAndMergeAnalysis::mergeAccessStruct(
@@ -678,7 +710,7 @@ void AccessConflictAndMergeAnalysis::visitBeginAccess(
678710
// the reason for calling this method is to check for that.
679711
// logically, we only need to add an instructio to
680712
// out-of-scope conflict-free set when we visit end_access
681-
addOutOfScopeAccess(info, beginAccess);
713+
addOutOfScopeAccessMerge(info, beginAccess);
682714
}
683715

684716
void AccessConflictAndMergeAnalysis::visitEndAccess(EndAccessInst *endAccess,
@@ -709,7 +741,7 @@ void AccessConflictAndMergeAnalysis::visitEndAccess(EndAccessInst *endAccess,
709741
LLVM_DEBUG(llvm::dbgs() << "Got out of scope from " << *beginAccess << " to "
710742
<< *endAccess << "\n");
711743

712-
addOutOfScopeAccess(info, beginAccess);
744+
addOutOfScopeAccessInsert(info, beginAccess);
713745
}
714746

715747
void AccessConflictAndMergeAnalysis::detectApplyConflicts(

test/SILOptimizer/access_enforcement_opts.sil

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1650,3 +1650,65 @@ bb0(%0 : $TestClass):
16501650
%12 = tuple ()
16511651
return %12 : $()
16521652
}
1653+
1654+
// public func testNestedReadMerging() {
1655+
// Checks bailing on nested read scopes
1656+
// We will create two scopes - nested conflict
1657+
//
1658+
// CHECK-LABEL: sil @testNestedReadMerging : $@convention(thin) () -> () {
1659+
// CHECK: [[GLOBAL:%.*]] = global_addr @globalX : $*X
1660+
// CHECK-NEXT: [[BEGIN:%.*]] = begin_access [read] [dynamic] [[GLOBAL]] : $*X
1661+
// CHECK-NEXT: load [[BEGIN]] : $*X
1662+
// CHECK-NEXT: load [[BEGIN]] : $*X
1663+
// CHECK-NEXT: [[BEGIN2:%.*]] = begin_access [read] [dynamic] [no_nested_conflict] [[GLOBAL]] : $*X
1664+
// CHECK-NEXT: load [[BEGIN2]] : $*X
1665+
// CHECK-NEXT: end_access [[BEGIN2]] : $*X
1666+
// CHECK-NEXT: end_access [[BEGIN]] : $*X
1667+
// CHECK-NOT: begin_access
1668+
// CHECK-LABEL: } // end sil function 'testNestedReadMerging'
1669+
sil @testNestedReadMerging : $@convention(thin) () -> () {
1670+
bb0:
1671+
%0 = global_addr @globalX: $*X
1672+
%1 = begin_access [read] [dynamic] %0 : $*X
1673+
%2 = load %1 : $*X
1674+
end_access %1 : $*X
1675+
%4 = begin_access [read] [dynamic] %0 : $*X
1676+
%5 = load %4 : $*X
1677+
%7 = begin_access [read] [dynamic] %0 : $*X
1678+
%8 = load %7 : $*X
1679+
end_access %7 : $*X
1680+
end_access %4 : $*X
1681+
%10 = tuple ()
1682+
return %10 : $()
1683+
}
1684+
1685+
// public func testNestedWriteBailout() {
1686+
// Same as testNestedReadBailout but with modify
1687+
// We will create two scopes - nested conflict
1688+
//
1689+
// CHECK-LABEL: sil @testNestedWriteBailout : $@convention(thin) () -> () {
1690+
// CHECK: [[GLOBAL:%.*]] = global_addr @globalX : $*X
1691+
// CHECK-NEXT: [[BEGIN:%.*]] = begin_access [modify] [dynamic] [[GLOBAL]] : $*X
1692+
// CHECK-NEXT: load [[BEGIN]] : $*X
1693+
// CHECK-NEXT: load [[BEGIN]] : $*X
1694+
// CHECK-NEXT: [[BEGIN2:%.*]] = begin_access [modify] [dynamic] [no_nested_conflict] [[GLOBAL]] : $*X
1695+
// CHECK-NEXT: load [[BEGIN2]] : $*X
1696+
// CHECK-NEXT: end_access [[BEGIN2]] : $*X
1697+
// CHECK-NEXT: end_access [[BEGIN]] : $*X
1698+
// CHECK-NOT: begin_access
1699+
// CHECK-LABEL: } // end sil function 'testNestedWriteBailout'
1700+
sil @testNestedWriteBailout : $@convention(thin) () -> () {
1701+
bb0:
1702+
%0 = global_addr @globalX: $*X
1703+
%1 = begin_access [modify] [dynamic] %0 : $*X
1704+
%2 = load %1 : $*X
1705+
end_access %1 : $*X
1706+
%4 = begin_access [modify] [dynamic] %0 : $*X
1707+
%5 = load %4 : $*X
1708+
%7 = begin_access [modify] [dynamic] %0 : $*X
1709+
%8 = load %7 : $*X
1710+
end_access %7 : $*X
1711+
end_access %4 : $*X
1712+
%10 = tuple ()
1713+
return %10 : $()
1714+
}

0 commit comments

Comments
 (0)