Skip to content

Commit

Permalink
[LAA] Add remarks for unbounded array access
Browse files Browse the repository at this point in the history
Adds new optimization remarks when loop vectorization fails due to
the compiler being unable to find bound of an array access inside
a loop

Differential Revision: https://reviews.llvm.org/D115873
  • Loading branch information
malJaj committed Feb 23, 2022
1 parent 22d0453 commit 9f1c6fb
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 10 deletions.
23 changes: 15 additions & 8 deletions llvm/lib/Analysis/LoopAccessAnalysis.cpp
Expand Up @@ -558,7 +558,7 @@ class AccessAnalysis {
/// (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.
Expand Down Expand Up @@ -732,7 +732,7 @@ bool AccessAnalysis::createCheckForAccess(RuntimePointerChecking &RtCheck,
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;
Expand Down Expand Up @@ -824,6 +824,7 @@ bool AccessAnalysis::canCheckPtrAtRT(RuntimePointerChecking &RtCheck,
DepSetId, TheLoop, RunningDepId, ASId,
ShouldCheckWrap, /*Assume=*/true)) {
CanDoAliasSetRT = false;
UncomputablePtr = Access.getPointer();
break;
}
}
Expand Down Expand Up @@ -2080,10 +2081,14 @@ void LoopAccessInfo::analyzeLoop(AAResults *AA, LoopInfo *LI,

// 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";
auto *I = dyn_cast_or_null<Instruction>(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;
Expand All @@ -2110,12 +2115,14 @@ void LoopAccessInfo::analyzeLoop(AAResults *AA, LoopInfo *LI,
PtrRtChecking->Need = true;

auto *SE = PSE->getSE();
CanDoRTIfNeeded = Accesses.canCheckPtrAtRT(*PtrRtChecking, SE, TheLoop,
SymbolicStrides, true);
UncomputablePtr = nullptr;
CanDoRTIfNeeded = Accesses.canCheckPtrAtRT(
*PtrRtChecking, SE, TheLoop, SymbolicStrides, UncomputablePtr, true);

// Check that we found the bounds for the pointer.
if (!CanDoRTIfNeeded) {
recordAnalysis("CantCheckMemDepsAtRunTime")
auto *I = dyn_cast_or_null<Instruction>(UncomputablePtr);
recordAnalysis("CantCheckMemDepsAtRunTime", I)
<< "cannot check memory dependencies at runtime";
LLVM_DEBUG(dbgs() << "LAA: Can't vectorize with memory checks\n");
CanVecMem = false;
Expand Down
Expand Up @@ -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

Expand Down Expand Up @@ -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: '
Expand Down
55 changes: 55 additions & 0 deletions llvm/test/Transforms/LoopVectorize/memory-dep-remarks.ll
Expand Up @@ -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) {
Expand Down Expand Up @@ -258,6 +291,23 @@ for.body: ; preds = %entry, %for.body
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
Expand Down Expand Up @@ -347,6 +397,11 @@ for.body: ; preds = %entry, %for.body
!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}
Expand Down

0 comments on commit 9f1c6fb

Please sign in to comment.