Index: lib/Analysis/ScopInfo.cpp =================================================================== --- lib/Analysis/ScopInfo.cpp +++ lib/Analysis/ScopInfo.cpp @@ -197,6 +197,12 @@ " disjunction sets that only have one instance"), cl::Hidden, cl::ZeroOrMore, cl::init(false), cl::cat(PollyCategory)); +static cl::opt + CleanRTC("polly-clean-rtc", + cl::desc("Propagate parameter restrictions form Avoid Single" + " Iteration assumptions to overflow check"), + cl::Hidden, cl::ZeroOrMore, cl::init(false), + cl::cat(PollyCategory)); //===----------------------------------------------------------------------===// // Create a sequence of two schedules. Either argument may be null and is @@ -3033,6 +3039,10 @@ void Scop::enforceAssumptionsForAvoidsingleIter() { AssumedContext = AssumedContext.intersect(getRestrictDomainParams()); + if (CleanRTC) + InvalidContext = InvalidContext.intersect_params(RestrictDomainParams) + .coalesce() + .gist_params(RestrictDomainParams); } MemoryAccess *Scop::lookupBasePtrAccess(MemoryAccess *MA) { Index: test/ScopDetect/model-dowhile-update-rtc.ll =================================================================== --- /dev/null +++ test/ScopDetect/model-dowhile-update-rtc.ll @@ -0,0 +1,79 @@ +; REQUIRES: asserts + +; RUN: opt %loadPolly -S -O3 -debug-only=polly-ast -debug-only=polly-scops\ +; RUN: -polly-ast -polly-avoid-singular-loops=true -polly-clean-rtc=false\ +; RUN: --disable-output %s |& FileCheck %s --check-prefix=NOFIXRTC + +; RUN: opt %loadPolly -S -O3 -debug-only=polly-ast -debug-only=polly-scops\ +; RUN: -polly-ast -polly-avoid-singular-loops=true -polly-clean-rtc=true\ +; RUN: --disable-output %s |& FileCheck %s --check-prefix=FIXRTC + +; RUN: opt %loadPolly -S -O3 -debug-only=polly-ast -debug-only=polly-scops\ +; RUN: -polly-ast -polly-avoid-singular-loops=false\ +; RUN: --disable-output %s |& FileCheck %s --check-prefix=NOFIXALIASGROUP + +; RUN: opt %loadPolly -S -O3 -debug-only=polly-ast -debug-only=polly-scops\ +; RUN: -polly-ast -polly-avoid-singular-loops=true\ +; RUN: --disable-output %s |& FileCheck %s --check-prefix=FIXALIASGROUP + +; Original C code: +;void foo(int* A, int* B, unsigned n) { +; +; unsigned idx =5; +; do { +; A[n+idx] += B[n+idx]; +; idx++; +; } while (idx <= n); +;} + +; This test checks that assumptions for the Trip Count added by modeling +; do-while like loops can be used to simplify the runtime check for the Scop. + +; First two run lines demonstrate ww are able to get rid of "n <= -1" in the +; RTC since we added the assumption "n >= 5" by cleaning up the overflow check +; (InvalidContext). + +; Last two run lines demostrate that the AliasGroups are simplified since +; they no longer have to check for values of n where 0 <= n <= 4. + +; NOFIXRTC: Invalid Context: +; NOFIXRTC-NEXT: [n] -> { : n >= 1073741824 or n < 0 } +; NOFIXRTC: :: isl ast :: foo +; NOFIXRTC: n <= -1 + +; FIXRTC: Invalid Context: +; FIXRTC-NEXT: [n] -> { : n >= 1073741824 } +; FIXRTC: :: isl ast :: foo +; FIXRTC-NOT: n <= -1 + +; NOFIXALIASGROUP: Alias Groups +; NOFIXALIASGROUP-NEXT: 0 <= n <= 4 + +; FIXALIASGROUP: Alias Groups +; FIXALIASGROUP-NOT: 0 <= n <= 4 + +; Function Attrs: norecurse nounwind +define dso_local void @foo(i32* nocapture %A, i32* nocapture readonly %B, i32 %n) local_unnamed_addr #0 { +entry: + br label %entry.split + +entry.split: ; preds = %entry + br label %do.body + +do.body: ; preds = %do.body, %entry.split + %idx.0 = phi i32 [ 5, %entry.split ], [ %inc, %do.body ] + %add = add i32 %idx.0, %n + %idxprom = zext i32 %add to i64 + %arrayidx = getelementptr inbounds i32, i32* %B, i64 %idxprom + %0 = load i32, i32* %arrayidx + %arrayidx3 = getelementptr inbounds i32, i32* %A, i64 %idxprom + %1 = load i32, i32* %arrayidx3 + %add4 = add nsw i32 %1, %0 + store i32 %add4, i32* %arrayidx3 + %inc = add i32 %idx.0, 1 + %cmp = icmp ugt i32 %inc, %n + br i1 %cmp, label %do.end, label %do.body + +do.end: ; preds = %do.body + ret void +}