Skip to content

Commit eaf2a06

Browse files
committed
[LAA] Drop alias scope metadata that is not valid across iterations
LAA currently adds memory locations with their original AATags to AST. However, scoped alias AATags may be valid only within one loop iteration, while LAA reasons across iterations. Fix this by determining which alias scopes are defined inside the loop, and drop AATags that reference these scopes. Fixes #79137.
1 parent 0c02b2e commit eaf2a06

File tree

2 files changed

+56
-8
lines changed

2 files changed

+56
-8
lines changed

llvm/lib/Analysis/LoopAccessAnalysis.cpp

+46-7
Original file line numberDiff line numberDiff line change
@@ -657,25 +657,27 @@ class AccessAnalysis {
657657

658658
AccessAnalysis(Loop *TheLoop, AAResults *AA, LoopInfo *LI,
659659
MemoryDepChecker::DepCandidates &DA,
660-
PredicatedScalarEvolution &PSE)
661-
: TheLoop(TheLoop), BAA(*AA), AST(BAA), LI(LI), DepCands(DA), PSE(PSE) {
660+
PredicatedScalarEvolution &PSE,
661+
SmallPtrSetImpl<MDNode *> &LoopAliasScopes)
662+
: TheLoop(TheLoop), BAA(*AA), AST(BAA), LI(LI), DepCands(DA), PSE(PSE),
663+
LoopAliasScopes(LoopAliasScopes) {
662664
// We're analyzing dependences across loop iterations.
663665
BAA.enableCrossIterationMode();
664666
}
665667

666668
/// Register a load and whether it is only read from.
667669
void addLoad(MemoryLocation &Loc, Type *AccessTy, bool IsReadOnly) {
668-
Value *Ptr = const_cast<Value*>(Loc.Ptr);
669-
AST.add(Loc.getWithNewSize(LocationSize::beforeOrAfterPointer()));
670+
Value *Ptr = const_cast<Value *>(Loc.Ptr);
671+
AST.add(adjustLoc(Loc));
670672
Accesses[MemAccessInfo(Ptr, false)].insert(AccessTy);
671673
if (IsReadOnly)
672674
ReadOnlyPtr.insert(Ptr);
673675
}
674676

675677
/// Register a store.
676678
void addStore(MemoryLocation &Loc, Type *AccessTy) {
677-
Value *Ptr = const_cast<Value*>(Loc.Ptr);
678-
AST.add(Loc.getWithNewSize(LocationSize::beforeOrAfterPointer()));
679+
Value *Ptr = const_cast<Value *>(Loc.Ptr);
680+
AST.add(adjustLoc(Loc));
679681
Accesses[MemAccessInfo(Ptr, true)].insert(AccessTy);
680682
}
681683

@@ -731,6 +733,32 @@ class AccessAnalysis {
731733
private:
732734
typedef MapVector<MemAccessInfo, SmallSetVector<Type *, 1>> PtrAccessMap;
733735

736+
/// Adjust the MemoryLocation so that it represents accesses to this
737+
/// location across all iterations, rather than a single one.
738+
MemoryLocation adjustLoc(MemoryLocation Loc) const {
739+
// The accessed location varies within the loop, but remains within the
740+
// underlying object.
741+
Loc.Size = LocationSize::beforeOrAfterPointer();
742+
Loc.AATags.Scope = adjustAliasScopeList(Loc.AATags.Scope);
743+
Loc.AATags.NoAlias = adjustAliasScopeList(Loc.AATags.NoAlias);
744+
return Loc;
745+
}
746+
747+
/// Drop alias scopes that are only valid within a single loop iteration.
748+
MDNode *adjustAliasScopeList(MDNode *ScopeList) const {
749+
if (!ScopeList)
750+
return nullptr;
751+
752+
// For the sake of simplicity, drop the whole scope list if any scope is
753+
// iteration-local.
754+
if (any_of(ScopeList->operands(), [&](Metadata *Scope) {
755+
return LoopAliasScopes.contains(cast<MDNode>(Scope));
756+
}))
757+
return nullptr;
758+
759+
return ScopeList;
760+
}
761+
734762
/// Go over all memory access and check whether runtime pointer checks
735763
/// are needed and build sets of dependency check candidates.
736764
void processMemAccesses();
@@ -775,6 +803,10 @@ class AccessAnalysis {
775803
PredicatedScalarEvolution &PSE;
776804

777805
DenseMap<Value *, SmallVector<const Value *, 16>> UnderlyingObjects;
806+
807+
/// Alias scopes that are declared inside the loop, and as such not valid
808+
/// across iterations.
809+
SmallPtrSetImpl<MDNode *> &LoopAliasScopes;
778810
};
779811

780812
} // end anonymous namespace
@@ -2283,6 +2315,7 @@ void LoopAccessInfo::analyzeLoop(AAResults *AA, LoopInfo *LI,
22832315
// Holds the Load and Store instructions.
22842316
SmallVector<LoadInst *, 16> Loads;
22852317
SmallVector<StoreInst *, 16> Stores;
2318+
SmallPtrSet<MDNode *, 8> LoopAliasScopes;
22862319

22872320
// Holds all the different accesses in the loop.
22882321
unsigned NumReads = 0;
@@ -2326,6 +2359,11 @@ void LoopAccessInfo::analyzeLoop(AAResults *AA, LoopInfo *LI,
23262359
if (HasComplexMemInst)
23272360
continue;
23282361

2362+
// Record alias scopes defined inside the loop.
2363+
if (auto *Decl = dyn_cast<NoAliasScopeDeclInst>(&I))
2364+
for (Metadata *Op : Decl->getScopeList()->operands())
2365+
LoopAliasScopes.insert(cast<MDNode>(Op));
2366+
23292367
// Many math library functions read the rounding mode. We will only
23302368
// vectorize a loop if it contains known function calls that don't set
23312369
// the flag. Therefore, it is safe to ignore this read from memory.
@@ -2407,7 +2445,8 @@ void LoopAccessInfo::analyzeLoop(AAResults *AA, LoopInfo *LI,
24072445
}
24082446

24092447
MemoryDepChecker::DepCandidates DependentAccesses;
2410-
AccessAnalysis Accesses(TheLoop, AA, LI, DependentAccesses, *PSE);
2448+
AccessAnalysis Accesses(TheLoop, AA, LI, DependentAccesses, *PSE,
2449+
LoopAliasScopes);
24112450

24122451
// Holds the analyzed pointers. We don't want to call getUnderlyingObjects
24132452
// multiple times on the same object. If the ptr is accessed twice, once

llvm/test/Analysis/LoopAccessAnalysis/noalias-scope-decl.ll

+10-1
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,17 @@
77
define void @test_scope_in_loop(ptr %arg, i64 %num) {
88
; CHECK-LABEL: 'test_scope_in_loop'
99
; CHECK-NEXT: loop:
10-
; CHECK-NEXT: Memory dependences are safe
10+
; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop
11+
; CHECK-NEXT: Backward loop carried data dependence.
1112
; CHECK-NEXT: Dependences:
13+
; CHECK-NEXT: Backward:
14+
; CHECK-NEXT: %load.prev = load i8, ptr %prev.ptr, align 1, !alias.scope !0, !noalias !3 ->
15+
; CHECK-NEXT: store i8 %add, ptr %cur.ptr, align 1, !alias.scope !3
16+
; CHECK-EMPTY:
17+
; CHECK-NEXT: Forward:
18+
; CHECK-NEXT: %load.cur = load i8, ptr %cur.ptr, align 1, !alias.scope !3 ->
19+
; CHECK-NEXT: store i8 %add, ptr %cur.ptr, align 1, !alias.scope !3
20+
; CHECK-EMPTY:
1221
; CHECK-NEXT: Run-time memory checks:
1322
; CHECK-NEXT: Grouped accesses:
1423
; CHECK-EMPTY:

0 commit comments

Comments
 (0)