diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp --- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp +++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp @@ -598,6 +598,10 @@ //intrinsic property (such as TBAA metadata). AliasSetTracker AST; + /// Similar to above, but instead contains only the alias sets we care about + /// when doing runtime checks. + SmallVector ReducedAST; + LoopInfo *LI; /// Sets of potentially dependent accesses - members of one set share an @@ -714,7 +718,7 @@ // We assign a consecutive id to access from different alias sets. // Accesses between different groups doesn't need to be checked. unsigned ASId = 1; - for (auto &AS : AST) { + for (auto &AS : ReducedAST) { int NumReadPtrChecks = 0; int NumWritePtrChecks = 0; bool CanDoAliasSetRT = true; @@ -726,7 +730,7 @@ SmallVector Retries; - for (auto A : AS) { + for (auto A : *AS) { Value *Ptr = A.getValue(); bool IsWrite = Accesses.count(MemAccessInfo(Ptr, true)); MemAccessInfo Access(Ptr, IsWrite); @@ -836,6 +840,7 @@ (A.getInt() ? "write" : (ReadOnlyPtr.count(A.getPointer()) ? "read-only" : "read")) << ")\n"; }); + ReducedAST.clear(); // The AliasSetTracker has nicely partitioned our pointers by metadata // compatibility and potential for underlying-object overlap. As a result, we @@ -847,6 +852,7 @@ // (matching the original instruction order within each set). bool SetHasWrite = false; + bool AnalyzeAS = false; // Map of pointers to last access encountered. typedef DenseMap UnderlyingObjToAccessMap; @@ -903,6 +909,7 @@ if ((IsWrite || IsReadOnlyPtr) && SetHasWrite) { CheckDeps.push_back(Access); IsRTCheckAnalysisNeeded = true; + AnalyzeAS = true; } if (IsWrite) @@ -936,6 +943,8 @@ } } } + if (AnalyzeAS) + ReducedAST.push_back(&AS); } } diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/mult-stores-alias-set.ll b/llvm/test/Transforms/LoopVectorize/AArch64/mult-stores-alias-set.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/LoopVectorize/AArch64/mult-stores-alias-set.ll @@ -0,0 +1,67 @@ +; RUN: opt -loop-accesses -analyze -O3 -S < %s | FileCheck %s + +; In this particular loop we have a gather and two stores, where the +; alias sets are as follows: +; Alias Set A: 1. Gather load +; Alias Set B: 1. First store, 2. second store +; Our loop analysis code correctly determines that the two stores in a +; single alias set (B) don't actually alias with each other. However, +; this means we should only need to do runtime check analysis on alias +; set B, since we know that A does not alias with B. If we also do +; runtime check analysis of A we will produce an error saying we cannot +; determine the runtime array bounds of the gather load. This test +; makes sure we the analysis succeeds. + +; CHECK: Memory dependences are safe with run-time checks +; CHECK: %18 = bitcast float* %17 to i32* +; CHECK: %21 = bitcast float* %20 to i32* +define dso_local void @foo(float* noalias nocapture, float* noalias nocapture readonly, i32* noalias nocapture readonly, i32) { + %5 = icmp sgt i32 %3, 0 + br i1 %5, label %6, label %25 + +;