[RTC] Split alias groups according to read only base addresses
If there are multiple read only base addresses in an alias group we can split it into multiple alias groups each with only one read only access. This way we might reduce the number of comparisons significantly as it grows linear in the number of alias groups but exponential in their size. Differential Revision: http://reviews.llvm.org/D5435 llvm-svn: 218757
This commit is contained in:
parent
6c02c031b8
commit
13771738d3
|
@ -1198,17 +1198,22 @@ bool Scop::buildAliasGroups(AliasAnalysis &AA) {
|
||||||
// o) For each alias set we then map the aliasing pointers back to the
|
// o) For each alias set we then map the aliasing pointers back to the
|
||||||
// memory accesses we know, thus obtain groups of memory accesses which
|
// memory accesses we know, thus obtain groups of memory accesses which
|
||||||
// might alias.
|
// might alias.
|
||||||
// o) For each group with more then one base pointer we then compute minimal
|
// o) We split groups such that they contain at most one read only base
|
||||||
|
// address.
|
||||||
|
// o) For each group with more than one base pointer we then compute minimal
|
||||||
// and maximal accesses to each array in this group.
|
// and maximal accesses to each array in this group.
|
||||||
using AliasGroupTy = SmallVector<MemoryAccess *, 4>;
|
using AliasGroupTy = SmallVector<MemoryAccess *, 4>;
|
||||||
|
|
||||||
AliasSetTracker AST(AA);
|
AliasSetTracker AST(AA);
|
||||||
|
|
||||||
DenseMap<Value *, MemoryAccess *> PtrToAcc;
|
DenseMap<Value *, MemoryAccess *> PtrToAcc;
|
||||||
|
DenseSet<Value *> HasWriteAccess;
|
||||||
for (ScopStmt *Stmt : *this) {
|
for (ScopStmt *Stmt : *this) {
|
||||||
for (MemoryAccess *MA : *Stmt) {
|
for (MemoryAccess *MA : *Stmt) {
|
||||||
if (MA->isScalar())
|
if (MA->isScalar())
|
||||||
continue;
|
continue;
|
||||||
|
if (!MA->isRead())
|
||||||
|
HasWriteAccess.insert(MA->getBaseAddr());
|
||||||
Instruction *Acc = MA->getAccessInstruction();
|
Instruction *Acc = MA->getAccessInstruction();
|
||||||
PtrToAcc[getPointerOperand(*Acc)] = MA;
|
PtrToAcc[getPointerOperand(*Acc)] = MA;
|
||||||
AST.add(Acc);
|
AST.add(Acc);
|
||||||
|
@ -1227,19 +1232,54 @@ bool Scop::buildAliasGroups(AliasAnalysis &AA) {
|
||||||
AliasGroups.push_back(std::move(AG));
|
AliasGroups.push_back(std::move(AG));
|
||||||
}
|
}
|
||||||
|
|
||||||
SmallPtrSet<const Value *, 4> BaseValues;
|
DenseMap<const Value *, SmallPtrSet<MemoryAccess *, 8>> ReadOnlyPairs;
|
||||||
for (auto I = AliasGroups.begin(); I != AliasGroups.end();) {
|
SmallPtrSet<const Value *, 4> NonReadOnlyBaseValues;
|
||||||
BaseValues.clear();
|
for (AliasGroupTy &AG : AliasGroups) {
|
||||||
for (MemoryAccess *MA : *I)
|
NonReadOnlyBaseValues.clear();
|
||||||
BaseValues.insert(MA->getBaseAddr());
|
ReadOnlyPairs.clear();
|
||||||
if (BaseValues.size() > 1)
|
|
||||||
I++;
|
for (auto II = AG.begin(); II != AG.end();) {
|
||||||
else
|
Value *BaseAddr = (*II)->getBaseAddr();
|
||||||
I = AliasGroups.erase(I);
|
if (HasWriteAccess.count(BaseAddr)) {
|
||||||
|
NonReadOnlyBaseValues.insert(BaseAddr);
|
||||||
|
II++;
|
||||||
|
} else {
|
||||||
|
ReadOnlyPairs[BaseAddr].insert(*II);
|
||||||
|
II = AG.erase(II);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we don't have read only pointers check if there are at least two
|
||||||
|
// non read only pointers, otherwise clear the alias group.
|
||||||
|
if (ReadOnlyPairs.empty()) {
|
||||||
|
if (NonReadOnlyBaseValues.size() <= 1)
|
||||||
|
AG.clear();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we don't have non read only pointers clear the alias group.
|
||||||
|
if (NonReadOnlyBaseValues.empty()) {
|
||||||
|
AG.clear();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have both read only and non read only base pointers we combine
|
||||||
|
// the non read only ones with exactly one read only one at a time into a
|
||||||
|
// new alias group and clear the old alias group in the end.
|
||||||
|
for (const auto &ReadOnlyPair : ReadOnlyPairs) {
|
||||||
|
AliasGroupTy AGNonReadOnly = AG;
|
||||||
|
for (MemoryAccess *MA : ReadOnlyPair.second)
|
||||||
|
AGNonReadOnly.push_back(MA);
|
||||||
|
AliasGroups.push_back(std::move(AGNonReadOnly));
|
||||||
|
}
|
||||||
|
AG.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Valid = true;
|
bool Valid = true;
|
||||||
for (AliasGroupTy &AG : AliasGroups) {
|
for (AliasGroupTy &AG : AliasGroups) {
|
||||||
|
if (AG.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
MinMaxVectorTy *MinMaxAccesses = new MinMaxVectorTy();
|
MinMaxVectorTy *MinMaxAccesses = new MinMaxVectorTy();
|
||||||
MinMaxAccesses->reserve(AG.size());
|
MinMaxAccesses->reserve(AG.size());
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,8 @@
|
||||||
; NOAA-DAG: &MemRef_Float0[1024] <= &MemRef_Int0[0] || &MemRef_Int0[1024] <= &MemRef_Float0[0]
|
; NOAA-DAG: &MemRef_Float0[1024] <= &MemRef_Int0[0] || &MemRef_Int0[1024] <= &MemRef_Float0[0]
|
||||||
; NOAA-DAG: &MemRef_Float1[1024] <= &MemRef_Int0[0] || &MemRef_Int0[1024] <= &MemRef_Float1[0]
|
; NOAA-DAG: &MemRef_Float1[1024] <= &MemRef_Int0[0] || &MemRef_Int0[1024] <= &MemRef_Float1[0]
|
||||||
; NOAA-DAG: &MemRef_Int1[1024] <= &MemRef_Int0[0] || &MemRef_Int0[1024] <= &MemRef_Int1[0]
|
; NOAA-DAG: &MemRef_Int1[1024] <= &MemRef_Int0[0] || &MemRef_Int0[1024] <= &MemRef_Int1[0]
|
||||||
; NOAA-DAG: &MemRef_Float1[1024] <= &MemRef_Float0[0] || &MemRef_Float0[1024] <= &MemRef_Float1[0]
|
; NOAA-DAG: &MemRef_Float0[1024] <= &MemRef_Float1[0] || &MemRef_Float1[1024] <= &MemRef_Float0[0]
|
||||||
; NOAA-DAG: &MemRef_Int1[1024] <= &MemRef_Float0[0] || &MemRef_Float0[1024] <= &MemRef_Int1[0]
|
; NOAA-DAG: &MemRef_Int1[1024] <= &MemRef_Float0[0] || &MemRef_Float0[1024] <= &MemRef_Int1[0]
|
||||||
; NOAA-DAG: &MemRef_Int1[1024] <= &MemRef_Float1[0] || &MemRef_Float1[1024] <= &MemRef_Int1[0]
|
|
||||||
; NOAA: ))
|
; NOAA: ))
|
||||||
;
|
;
|
||||||
; TBAA: if (1 && (
|
; TBAA: if (1 && (
|
||||||
|
|
|
@ -39,14 +39,25 @@ for.end: ; preds = %for.body
|
||||||
!4 = metadata !{metadata !5, metadata !5, i64 0}
|
!4 = metadata !{metadata !5, metadata !5, i64 0}
|
||||||
!5 = metadata !{metadata !"float", metadata !2, i64 0}
|
!5 = metadata !{metadata !"float", metadata !2, i64 0}
|
||||||
|
|
||||||
; NOAA: Alias Groups (1):
|
; NOAA: Alias Groups (2):
|
||||||
|
; NOAA-NEXT: {{\[\[}}
|
||||||
; NOAA-DAG: <{ MemRef_Int0[(0)] }, { MemRef_Int0[(1024)] }>
|
; NOAA-DAG: <{ MemRef_Int0[(0)] }, { MemRef_Int0[(1024)] }>
|
||||||
; NOAA-DAG: <{ MemRef_Int1[(0)] }, { MemRef_Int1[(1024)] }>
|
; NOAA-DAG: <{ MemRef_{{(Int|Float)}}1[(0)] }, { MemRef_{{(Int|Float)}}1[(1024)] }>
|
||||||
; NOAA-DAG: <{ MemRef_Float0[(0)] }, { MemRef_Float0[(1024)] }>
|
; NOAA-DAG: <{ MemRef_Float0[(0)] }, { MemRef_Float0[(1024)] }>
|
||||||
; NOAA-DAG: <{ MemRef_Float1[(0)] }, { MemRef_Float1[(1024)] }>
|
; NOAA: {{\]\]}}
|
||||||
|
; NOAA-NEXT: {{\[\[}}
|
||||||
|
; NOAA-DAG: <{ MemRef_Int0[(0)] }, { MemRef_Int0[(1024)] }>
|
||||||
|
; NOAA-DAG: <{ MemRef_Float0[(0)] }, { MemRef_Float0[(1024)] }>
|
||||||
|
; NOAA-DAG: <{ MemRef_{{(Int|Float)}}1[(0)] }, { MemRef_{{(Int|Float)}}1[(1024)] }>
|
||||||
|
; NOAA: {{\]\]}}
|
||||||
|
|
||||||
; TBAA-DAG: Alias Groups (2):
|
|
||||||
|
; TBAA: Alias Groups (2):
|
||||||
|
; TBAA-NEXT: {{\[\[}}
|
||||||
; TBAA-DAG: <{ MemRef_Int0[(0)] }, { MemRef_Int0[(1024)] }>
|
; TBAA-DAG: <{ MemRef_Int0[(0)] }, { MemRef_Int0[(1024)] }>
|
||||||
; TBAA-DAG: <{ MemRef_Int1[(0)] }, { MemRef_Int1[(1024)] }>
|
; TBAA-DAG: <{ MemRef_Int1[(0)] }, { MemRef_Int1[(1024)] }>
|
||||||
|
; TBAA: {{\]\]}}
|
||||||
|
; TBAA-NEXT: {{\[\[}}
|
||||||
; TBAA-DAG: <{ MemRef_Float0[(0)] }, { MemRef_Float0[(1024)] }>
|
; TBAA-DAG: <{ MemRef_Float0[(0)] }, { MemRef_Float0[(1024)] }>
|
||||||
; TBAA-DAG: <{ MemRef_Float1[(0)] }, { MemRef_Float1[(1024)] }>
|
; TBAA-DAG: <{ MemRef_Float1[(0)] }, { MemRef_Float1[(1024)] }>
|
||||||
|
; TBBA: {{\]\]}}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
; RUN: opt %loadPolly -polly-code-generator=isl -polly-scops -analyze < %s | FileCheck %s
|
||||||
|
;
|
||||||
|
; void foo(float *A, float *B, float *C, long N) {
|
||||||
|
; for (long i = 0; i < N; i++)
|
||||||
|
; C[i] = A[i] + B[i];
|
||||||
|
; }
|
||||||
|
;
|
||||||
|
; CHECK: Alias Groups (2):
|
||||||
|
;
|
||||||
|
; This test case verifies that we do not create run-time checks for two
|
||||||
|
; read-only arrays.
|
||||||
|
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||||
|
|
||||||
|
define void @foo(float* %A, float* %B, float* %C, i64 %N) {
|
||||||
|
entry:
|
||||||
|
br label %for.body
|
||||||
|
|
||||||
|
for.body:
|
||||||
|
%indvar = phi i64 [ 0, %entry ], [ %indvar.next, %for.body ]
|
||||||
|
%arrayidx.A = getelementptr float* %A, i64 %indvar
|
||||||
|
%arrayidx.B = getelementptr float* %B, i64 %indvar
|
||||||
|
%arrayidx.C = getelementptr float* %C, i64 %indvar
|
||||||
|
%val.A = load float* %arrayidx.A
|
||||||
|
%val.B = load float* %arrayidx.B
|
||||||
|
%add = fadd float %val.A, %val.B
|
||||||
|
store float %add, float* %arrayidx.C
|
||||||
|
%indvar.next = add nsw i64 %indvar, 1
|
||||||
|
%exitcond = icmp ne i64 %indvar.next, %N
|
||||||
|
br i1 %exitcond, label %for.body, label %for.end
|
||||||
|
|
||||||
|
for.end:
|
||||||
|
ret void
|
||||||
|
}
|
Loading…
Reference in New Issue