[RTC] Use the domain to split alias groups.

We use a parametric abstraction of the domain to split alias groups
  if accesses cannot be executed under the same parameter evaluation.

  The two test cases check that we can remove alias groups if the
  pointers which might alias are never accessed under the same parameter
  evaluation and that the minimal/maximal accesses are not global but
  with regards to the parameter evaluation.

Differential Revision: http://reviews.llvm.org/D5436

llvm-svn: 218758
This commit is contained in:
Johannes Doerfert 2014-10-01 12:42:37 +00:00
parent 13771738d3
commit eeab05a084
3 changed files with 149 additions and 0 deletions

View File

@ -1191,6 +1191,12 @@ static int buildMinMaxAccess(__isl_take isl_set *Set, void *User) {
return 0;
}
static __isl_give isl_set *getAccessDomain(MemoryAccess *MA) {
isl_set *Domain = MA->getStatement()->getDomain();
Domain = isl_set_project_out(Domain, isl_dim_set, 0, isl_set_n_dim(Domain));
return isl_set_reset_tuple_id(Domain);
}
bool Scop::buildAliasGroups(AliasAnalysis &AA) {
// To create sound alias checks we perform the following steps:
// o) Use the alias analysis and an alias set tracker to build alias sets
@ -1198,6 +1204,10 @@ bool Scop::buildAliasGroups(AliasAnalysis &AA) {
// 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
// might alias.
// o) We divide each group based on the domains of the minimal/maximal
// accesses. That means two minimal/maximal accesses are only in a group
// if their access domains intersect, otherwise they are in different
// ones.
// 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
@ -1232,12 +1242,40 @@ bool Scop::buildAliasGroups(AliasAnalysis &AA) {
AliasGroups.push_back(std::move(AG));
}
// Split the alias groups based on their domain.
for (unsigned u = 0; u < AliasGroups.size(); u++) {
AliasGroupTy NewAG;
AliasGroupTy &AG = AliasGroups[u];
AliasGroupTy::iterator AGI = AG.begin();
isl_set *AGDomain = getAccessDomain(*AGI);
while (AGI != AG.end()) {
MemoryAccess *MA = *AGI;
isl_set *MADomain = getAccessDomain(MA);
if (isl_set_is_disjoint(AGDomain, MADomain)) {
NewAG.push_back(MA);
AGI = AG.erase(AGI);
isl_set_free(MADomain);
} else {
AGDomain = isl_set_union(AGDomain, MADomain);
AGI++;
}
}
if (NewAG.size() > 1)
AliasGroups.push_back(std::move(NewAG));
isl_set_free(AGDomain);
}
DenseMap<const Value *, SmallPtrSet<MemoryAccess *, 8>> ReadOnlyPairs;
SmallPtrSet<const Value *, 4> NonReadOnlyBaseValues;
for (AliasGroupTy &AG : AliasGroups) {
NonReadOnlyBaseValues.clear();
ReadOnlyPairs.clear();
if (AG.size() < 2) {
AG.clear();
continue;
}
for (auto II = AG.begin(); II != AG.end();) {
Value *BaseAddr = (*II)->getBaseAddr();
if (HasWriteAccess.count(BaseAddr)) {

View File

@ -0,0 +1,56 @@
; RUN: opt %loadPolly -polly-code-generator=isl -polly-scops -analyze < %s | FileCheck %s
;
; Check that there is no alias group because we either access A or B never both.
;
; CHECK: Alias Groups (0):
;
; void jd(int b, int *A, int *B) {
; for (int i = 0; i < 1024; i++) {
; if (b)
; A[i] = A[i - 1];
; else
; B[i] = B[i - 1];
; }
; }
;
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
define void @jd(i32 %b, i32* %A, i32* %B) {
entry:
br label %for.cond
for.cond: ; preds = %for.inc, %entry
%indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
%exitcond = icmp ne i64 %indvars.iv, 1024
br i1 %exitcond, label %for.body, label %for.end
for.body: ; preds = %for.cond
%tobool = icmp eq i32 %b, 0
br i1 %tobool, label %if.else, label %if.then
if.then: ; preds = %for.body
%tmp = add nsw i64 %indvars.iv, -1
%arrayidx = getelementptr inbounds i32* %A, i64 %tmp
%tmp3 = load i32* %arrayidx, align 4
%arrayidx2 = getelementptr inbounds i32* %A, i64 %indvars.iv
store i32 %tmp3, i32* %arrayidx2, align 4
br label %if.end
if.else: ; preds = %for.body
%tmp4 = add nsw i64 %indvars.iv, -1
%arrayidx5 = getelementptr inbounds i32* %B, i64 %tmp4
%tmp5 = load i32* %arrayidx5, align 4
%arrayidx7 = getelementptr inbounds i32* %B, i64 %indvars.iv
store i32 %tmp5, i32* %arrayidx7, align 4
br label %if.end
if.end: ; preds = %if.else, %if.then
br label %for.inc
for.inc: ; preds = %if.end
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
br label %for.cond
for.end: ; preds = %for.cond
ret void
}

View File

@ -0,0 +1,55 @@
; RUN: opt %loadPolly -polly-code-generator=isl -polly-scops -analyze < %s | FileCheck %s
;
; Check that we create two alias groups since the mininmal/maximal accesses
; depend on %b.
;
; CHECK: Alias Groups (2):
;
; void jd(int b, int *A, int *B) {
; for (int i = 0; i < 1024; i++) {
; if (b)
; A[i] = B[5];
; else
; B[i] = A[7];
; }
; }
;
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
define void @jd(i32 %b, i32* %A, i32* %B) {
entry:
br label %for.cond
for.cond: ; preds = %for.inc, %entry
%indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
%exitcond = icmp ne i64 %indvars.iv, 1024
br i1 %exitcond, label %for.body, label %for.end
for.body: ; preds = %for.cond
%tobool = icmp eq i32 %b, 0
br i1 %tobool, label %if.else, label %if.then
if.then: ; preds = %for.body
%arrayidx = getelementptr inbounds i32* %B, i64 5
%tmp = load i32* %arrayidx, align 4
%arrayidx1 = getelementptr inbounds i32* %A, i64 %indvars.iv
store i32 %tmp, i32* %arrayidx1, align 4
br label %if.end
if.else: ; preds = %for.body
%arrayidx2 = getelementptr inbounds i32* %A, i64 7
%tmp1 = load i32* %arrayidx2, align 4
%arrayidx4 = getelementptr inbounds i32* %B, i64 %indvars.iv
store i32 %tmp1, i32* %arrayidx4, align 4
br label %if.end
if.end: ; preds = %if.else, %if.then
br label %for.inc
for.inc: ; preds = %if.end
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
br label %for.cond
for.end: ; preds = %for.cond
ret void
}