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 @@ -560,7 +560,8 @@ /// (i.e. the pointers have computable bounds). bool canCheckPtrAtRT(RuntimePointerChecking &RtCheck, ScalarEvolution *SE, Loop *TheLoop, const ValueToValueMap &Strides, - bool ShouldCheckWrap = false); + bool ShouldCheckWrap = false, + Value **UncomputablePtr = nullptr); /// Goes over all memory accesses, checks whether a RT check is needed /// and builds sets of dependent accesses. @@ -710,7 +711,7 @@ bool AccessAnalysis::canCheckPtrAtRT(RuntimePointerChecking &RtCheck, ScalarEvolution *SE, Loop *TheLoop, const ValueToValueMap &StridesMap, - bool ShouldCheckWrap) { + bool ShouldCheckWrap, Value **UncomputablePtr) { // Find pointers with computable bounds. We are going to use this information // to place a runtime bound check. bool CanDoRT = true; @@ -798,6 +799,8 @@ TheLoop, RunningDepId, ASId, ShouldCheckWrap, /*Assume=*/true)) { CanDoAliasSetRT = false; + if (UncomputablePtr) + *UncomputablePtr = Access.getPointer(); break; } } @@ -2072,10 +2075,15 @@ // Find pointers with computable bounds. We are going to use this information // to place a runtime bound check. - bool CanDoRTIfNeeded = Accesses.canCheckPtrAtRT(*PtrRtChecking, PSE->getSE(), - TheLoop, SymbolicStrides); + Value *UncomputablePtr = nullptr; + bool CanDoRTIfNeeded = + Accesses.canCheckPtrAtRT(*PtrRtChecking, PSE->getSE(), TheLoop, + SymbolicStrides, false, &UncomputablePtr); if (!CanDoRTIfNeeded) { - recordAnalysis("CantIdentifyArrayBounds") << "cannot identify array bounds"; + if (auto *I = dyn_cast_or_null(UncomputablePtr)) { + recordAnalysis("CantIdentifyArrayBounds", I) + << "cannot identify array bounds"; + } LLVM_DEBUG(dbgs() << "LAA: We can't vectorize because we can't find " << "the array bounds.\n"); CanVecMem = false; diff --git a/llvm/test/Transforms/LoopVectorize/X86/vectorization-remarks-missed.ll b/llvm/test/Transforms/LoopVectorize/X86/vectorization-remarks-missed.ll --- a/llvm/test/Transforms/LoopVectorize/X86/vectorization-remarks-missed.ll +++ b/llvm/test/Transforms/LoopVectorize/X86/vectorization-remarks-missed.ll @@ -32,7 +32,7 @@ ; A[i] = A[B[i]]; ; } ; CHECK: remark: source.cpp:19:5: loop not vectorized: cannot identify array bounds -; CHECK: remark: source.cpp:19:5: loop not vectorized +; CHECK: remark: source.cpp:18:8: loop not vectorized ; CHECK: warning: source.cpp:19:5: loop not vectorized: the optimizer was unable to perform the requested transformation; the transformation might be disabled or specified as part of an unsupported transformation ordering ; int foo(); @@ -197,7 +197,7 @@ br i1 %cmp9, label %for.body.preheader, label %for.end, !dbg !32, !llvm.loop !34 for.body.preheader: ; preds = %entry - br label %for.body, !dbg !35 + br label %for.body, !dbg !32 for.body: ; preds = %for.body.preheader, %for.body %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %for.body.preheader ] diff --git a/llvm/test/Transforms/LoopVectorize/memory-dep-remarks.ll b/llvm/test/Transforms/LoopVectorize/memory-dep-remarks.ll --- a/llvm/test/Transforms/LoopVectorize/memory-dep-remarks.ll +++ b/llvm/test/Transforms/LoopVectorize/memory-dep-remarks.ll @@ -1,6 +1,39 @@ ; RUN: opt -passes='loop(require),function(loop-vectorize)' -disable-output -pass-remarks-analysis=loop-vectorize < %s 2>&1 | FileCheck %s target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" +; // Loop has an array element B[i] (%arrayidx in IR) being used as index to +; // another array (A), and since the value of B[i] is unknown, +; // the bound for array A is unknown. +; void test_unknown_bounds(int* A, int* B, int n) { +; for(int i = 0; i < n ; ++i) +; A[i] = A[B[i]] + 1; +; } + +; CHECK: remark: source.c:4:16: loop not vectorized: cannot identify array bounds + +define void @test_unknown_bounds(i32* nocapture %A, i32* nocapture readonly %B, i64 %n) !dbg !13 { +entry: + %cmp10 = icmp sgt i64 %n, 0 + br i1 %cmp10, label %for.body, label %for.cond.cleanup + +for.cond.cleanup: ; preds = %for.body, %entry + ret void + +for.body: ; preds = %entry, %for.body + %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] + %arrayidx = getelementptr inbounds i32, i32* %B, i64 %indvars.iv + %0 = load i32, i32* %arrayidx, align 4 + %idxprom1 = sext i32 %0 to i64, !dbg !35 + %arrayidx2 = getelementptr inbounds i32, i32* %A, i64 %idxprom1, !dbg !35 + %1 = load i32, i32* %arrayidx2, align 4, !dbg !35 + %add = add nsw i32 %1, 1 + %arrayidx4 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv + store i32 %add, i32* %arrayidx4, align 4 + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 + %exitcond.not = icmp eq i64 %indvars.iv.next, %n + br i1 %exitcond.not, label %for.cond.cleanup, label %for.body, !dbg !28 +} + ; // a) Dependence::NoDep ; // Loop containing only reads (here of the array A) does not hinder vectorization ; void test_nodep(int n, int* A, int* B) {