Index: include/llvm/Analysis/LoopAccessAnalysis.h =================================================================== --- include/llvm/Analysis/LoopAccessAnalysis.h +++ include/llvm/Analysis/LoopAccessAnalysis.h @@ -345,6 +345,10 @@ /// to needsChecking. bool needsAnyChecking(const SmallVectorImpl *PtrPartition) const; + /// \brief Returns the number of run-time checks required according to + /// needsChecking. + unsigned getNumberOfChecks(const SmallVectorImpl *PtrPartition) const; + /// \brief Print the list run-time memory checks necessary. /// /// If \p PtrPartition is set, it contains the partition number for Index: lib/Analysis/LoopAccessAnalysis.cpp =================================================================== --- lib/Analysis/LoopAccessAnalysis.cpp +++ lib/Analysis/LoopAccessAnalysis.cpp @@ -177,15 +177,21 @@ } } -bool LoopAccessInfo::RuntimePointerCheck::needsAnyChecking( +unsigned LoopAccessInfo::RuntimePointerCheck::getNumberOfChecks( const SmallVectorImpl *PtrPartition) const { unsigned NumPointers = Pointers.size(); + unsigned CheckCount = 0; for (unsigned I = 0; I < NumPointers; ++I) for (unsigned J = I + 1; J < NumPointers; ++J) if (needsChecking(I, J, PtrPartition)) - return true; - return false; + CheckCount++; + return CheckCount; +} + +bool LoopAccessInfo::RuntimePointerCheck::needsAnyChecking( + const SmallVectorImpl *PtrPartition) const { + return getNumberOfChecks(PtrPartition) != 0; } namespace { @@ -220,7 +226,8 @@ } /// \brief Check whether we can check the pointers at runtime for - /// non-intersection. + /// non-intersection. Returns true when we have 0 pointers + /// (a check on 0 pointers for non-intersection will always return true). bool canCheckPtrAtRT(LoopAccessInfo::RuntimePointerCheck &RtCheck, unsigned &NumComparisons, ScalarEvolution *SE, Loop *TheLoop, const ValueToValueMap &Strides, @@ -354,16 +361,11 @@ } } - if (IsDepCheckNeeded && CanDoRT && RunningDepId == 2) - NumComparisons += 0; // Only one dependence set. - else { - NumComparisons += (NumWritePtrChecks * (NumReadPtrChecks + - NumWritePtrChecks - 1)); - } - ++ASId; } + NumComparisons = RtCheck.getNumberOfChecks(nullptr); + // If the pointers that we would use for the bounds comparison have different // address spaces, assume the values aren't directly comparable, so we can't // use them for the runtime check. We also have to assume they could @@ -1127,17 +1129,18 @@ // Find pointers with computable bounds. We are going to use this information // to place a runtime bound check. - bool CanDoRT = false; - if (NeedRTCheck) - CanDoRT = Accesses.canCheckPtrAtRT(PtrRtCheck, NumComparisons, SE, TheLoop, - Strides); + bool CanDoRT = NeedRTCheck ? + Accesses.canCheckPtrAtRT(PtrRtCheck, + NumComparisons, + SE, TheLoop, + Strides) : true; DEBUG(dbgs() << "LAA: We need to do " << NumComparisons << " pointer comparisons.\n"); // If we only have one set of dependences to check pointers among we don't // need a runtime check. - if (NumComparisons == 0 && NeedRTCheck) + if (NumComparisons == 0 && NeedRTCheck && CanDoRT) NeedRTCheck = false; // Check that we found the bounds for the pointer. Index: test/Analysis/LoopAccessAnalysis/number-of-memchecks.ll =================================================================== --- test/Analysis/LoopAccessAnalysis/number-of-memchecks.ll +++ test/Analysis/LoopAccessAnalysis/number-of-memchecks.ll @@ -0,0 +1,58 @@ +; RUN: opt -loop-accesses -analyze < %s | FileCheck %s + +; 3 reads and 3 writes should need 12 memchecks + +target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128" +target triple = "aarch64--linux-gnueabi" + +; CHECK: Memory dependences are safe with run-time checks +; Memory dependecies have labels starting from 0, so in +; order to verify that we have n checks, we look for +; (n-1): and not n:. + +; CHECK: Run-time memory checks: +; CHECK-NEXT: 0: +; CHECK: 11: +; CHECK-NOT: 12: + +define void @testf(i16* %a, + i16* %b, + i16* %c, + i16* %d, + i16* %e, + i16* %f) { +entry: + br label %for.body + +for.body: ; preds = %for.body, %entry + %ind = phi i64 [ 0, %entry ], [ %add, %for.body ] + + %add = add nuw nsw i64 %ind, 1 + + %arrayidxA = getelementptr inbounds i16, i16* %a, i64 %ind + %loadA = load i16, i16* %arrayidxA, align 2 + + %arrayidxB = getelementptr inbounds i16, i16* %b, i64 %ind + %loadB = load i16, i16* %arrayidxB, align 2 + + %arrayidxC = getelementptr inbounds i16, i16* %c, i64 %ind + %loadC = load i16, i16* %arrayidxC, align 2 + + %mul = mul i16 %loadB, %loadA + %mul1 = mul i16 %mul, %loadC + + %arrayidxD = getelementptr inbounds i16, i16* %d, i64 %ind + store i16 %mul1, i16* %arrayidxD, align 2 + + %arrayidxE = getelementptr inbounds i16, i16* %e, i64 %ind + store i16 %mul, i16* %arrayidxE, align 2 + + %arrayidxF = getelementptr inbounds i16, i16* %f, i64 %ind + store i16 %mul1, i16* %arrayidxF, align 2 + + %exitcond = icmp eq i64 %add, 20 + br i1 %exitcond, label %for.end, label %for.body + +for.end: ; preds = %for.body + ret void +}