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 @@ -559,7 +559,7 @@ /// (i.e. the pointers have computable bounds). bool canCheckPtrAtRT(RuntimePointerChecking &RtCheck, ScalarEvolution *SE, Loop *TheLoop, const ValueToValueMap &Strides, - bool ShouldCheckWrap = false); + Value *&UncomputablePtr, bool ShouldCheckWrap = false); /// Goes over all memory accesses, checks whether a RT check is needed /// and builds sets of dependent accesses. @@ -732,7 +732,7 @@ bool AccessAnalysis::canCheckPtrAtRT(RuntimePointerChecking &RtCheck, ScalarEvolution *SE, Loop *TheLoop, const ValueToValueMap &StridesMap, - bool ShouldCheckWrap) { + Value *&UncomputablePtr, bool ShouldCheckWrap) { // Find pointers with computable bounds. We are going to use this information // to place a runtime bound check. bool CanDoRT = true; @@ -820,6 +820,7 @@ TheLoop, RunningDepId, ASId, ShouldCheckWrap, /*Assume=*/true)) { CanDoAliasSetRT = false; + UncomputablePtr = Access.getPointer(); break; } } @@ -2069,10 +2070,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, UncomputablePtr, false); 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; @@ -2099,8 +2105,9 @@ PtrRtChecking->Need = true; auto *SE = PSE->getSE(); - CanDoRTIfNeeded = Accesses.canCheckPtrAtRT(*PtrRtChecking, SE, TheLoop, - SymbolicStrides, true); + Value *UncomputablePtr2; + CanDoRTIfNeeded = Accesses.canCheckPtrAtRT( + *PtrRtChecking, SE, TheLoop, SymbolicStrides, UncomputablePtr2, true); // Check that we found the bounds for the pointer. if (!CanDoRTIfNeeded) { 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 @@ -31,7 +31,7 @@ ; for (int i = 0; i < Length; i++) ; A[i] = A[B[i]]; ; } -; CHECK: remark: source.cpp:18:8: loop not vectorized: cannot identify array bounds +; CHECK: remark: source.cpp:19:5: loop not vectorized: cannot identify array bounds ; CHECK: remark: source.cpp:18:8: loop not vectorized (Force=true) ; CHECK: warning: source.cpp:18:8: 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 @@ -76,7 +76,7 @@ ; YAML-NEXT: --- !Analysis ; YAML-NEXT: Pass: '' ; YAML-NEXT: Name: CantIdentifyArrayBounds -; YAML-NEXT: DebugLoc: { File: source.cpp, Line: 18, Column: 8 } +; YAML-NEXT: DebugLoc: { File: source.cpp, Line: 19, Column: 5 } ; YAML-NEXT: Function: _Z17test_array_boundsPiS_i ; YAML-NEXT: Args: ; YAML-NEXT: - String: 'loop not vectorized: ' 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 @@ -4,6 +4,39 @@ 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 n, int* A, int* B) { +; 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(i64 %n, i32* nocapture %A, i32* nocapture readonly %B) !dbg !13 { +entry: + %cmp10 = icmp sgt i64 %n, 0 + br i1 %cmp10, label %for.body, label %for.cond.cleanup + +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 + +for.cond.cleanup: ; preds = %for.body, %entry + ret void +} + ; // 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) { @@ -258,6 +291,23 @@ ret void } +; YAML: --- !Analysis +; YAML-NEXT: Pass: loop-vectorize +; YAML-NEXT: Name: CantIdentifyArrayBounds +; YAML-NEXT: DebugLoc: { File: source.c, Line: 4, Column: 16 } +; YAML-NEXT: Function: test_unknown_bounds +; YAML-NEXT: Args: +; YAML-NEXT: - String: 'loop not vectorized: ' +; YAML-NEXT: - String: cannot identify array bounds +; YAML-NEXT: ... +; YAML-NEXT: --- !Missed +; YAML-NEXT: Pass: loop-vectorize +; YAML-NEXT: Name: MissedDetails +; YAML-NEXT: DebugLoc: { File: source.c, Line: 3, Column: 5 } +; YAML-NEXT: Function: test_unknown_bounds +; YAML-NEXT: Args: +; YAML-NEXT: - String: loop not vectorized +; YAML-NEXT: ... ; YAML: --- !Analysis ; YAML-NEXT: Pass: loop-vectorize ; YAML-NEXT: Name: UnsafeDep @@ -347,6 +397,11 @@ !1 = !DIFile(filename: "source.c", directory: "") !2 = !{} !4 = !{i32 2, !"Debug Info Version", i32 3} +!13 = distinct !DISubprogram(name: "test_unknown_bounds", scope: !1, file: !1, line: 2, type: !45, scopeLine: 2, unit: !0, retainedNodes: !2) +!23 = distinct !DILexicalBlock(scope: !13, file: !1, line: 3, column: 5) +!27 = distinct !DILexicalBlock(scope: !23, file: !1, line: 3, column: 5) +!28 = !DILocation(line: 3, column: 5, scope: !23) +!35 = !DILocation(line: 4, column: 16, scope: !27) !44 = distinct !DISubprogram(name: "test_nodep", scope: !1, file: !1, line: 14, type: !45, scopeLine: 14, unit: !0, retainedNodes: !2) !45 = !DISubroutineType(types: !46) !46 = !{null, !18, !16, !16}