-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[LV] Add initial legality checks for loops with unbound loads. #152422
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 8 commits
dc5b7c1
78f05df
f5315f8
d3246bd
eb316ee
faa6112
b206c9f
72383dd
0c1d007
e22c486
2a37216
abb0120
6b920f4
22dee5b
e88d5d4
12e6dc9
3284452
10156ca
16b5376
357ff34
ead7a78
9e98d12
f18dae7
9dc5a7a
380e064
93db706
43976f7
51a8329
7a99472
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1760,16 +1760,39 @@ bool LoopVectorizationLegality::isVectorizableEarlyExitLoop() { | |
assert(LatchBB->getUniquePredecessor() == SingleUncountableExitingBlock && | ||
"Expected latch predecessor to be the early exiting block"); | ||
|
||
// TODO: Handle loops that may fault. | ||
Predicates.clear(); | ||
if (!isDereferenceableReadOnlyLoop(TheLoop, PSE.getSE(), DT, AC, | ||
&Predicates)) { | ||
SmallVector<LoadInst *, 4> NonDerefLoads; | ||
if (!isReadOnlyLoopWithSafeOrSpeculativeLoads(TheLoop, PSE.getSE(), DT, AC, | ||
&NonDerefLoads, &Predicates)) { | ||
reportVectorizationFailure( | ||
"Loop may fault", | ||
"Cannot vectorize potentially faulting early exit loop", | ||
"PotentiallyFaultingEarlyExitLoop", ORE, TheLoop); | ||
arcbbb marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
return false; | ||
} | ||
// Check non-dereferenceable loads if any. | ||
for (LoadInst *LI : NonDerefLoads) { | ||
// Only support unit-stride access for now. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just a question about potential AArch64 support, SVE has first-fault gathers IIUC which could be used for strided accesses. I presume we don't need to check for alignment there? From quickly scanning the docs it looks like an unaligned access non-first-fault will be handled the same as any other non-first-fault. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, SVE's first faulting gathers have the same alignment rules as normal gathers, so no extra checks required. |
||
int Stride = isConsecutivePtr(LI->getType(), LI->getPointerOperand()); | ||
arcbbb marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (Stride != 1) { | ||
reportVectorizationFailure("Loop contains strided unbound access", | ||
arcbbb marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
"Cannot vectorize early exit loop with " | ||
"speculative strided load", | ||
"SpeculativeNonUnitStrideLoadEarlyExitLoop", | ||
ORE, TheLoop); | ||
return false; | ||
} | ||
if (!TTI->isLegalSpeculativeLoad(LI->getType(), LI->getAlign())) { | ||
reportVectorizationFailure("Loop may fault", | ||
"Cannot vectorize early exit loop with " | ||
"illegal speculative load", | ||
"IllegalSpeculativeLoadEarlyExitLoop", ORE, | ||
TheLoop); | ||
return false; | ||
} | ||
SpeculativeLoads.insert(LI); | ||
LLVM_DEBUG(dbgs() << "LV: Found speculative load: " << *LI << "\n"); | ||
} | ||
|
||
[[maybe_unused]] const SCEV *SymbolicMaxBTC = | ||
PSE.getSymbolicMaxBackedgeTakenCount(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
; REQUIRES: asserts | ||
; RUN: opt -passes=loop-vectorize -debug-only=loop-vectorize -disable-output 2>&1 -mtriple=riscv64 -mattr=+v -S %s | FileCheck %s | ||
|
||
define ptr @unsupported_data_type(ptr %first, ptr %last, i128 %value) { | ||
; CHECK-LABEL: LV: Checking a loop in 'unsupported_data_type' | ||
; CHECK: LV: Not vectorizing: Loop may fault. | ||
entry: | ||
%cond = icmp eq ptr %first, %last | ||
br i1 %cond, label %return, label %for.body | ||
|
||
for.body: | ||
%first.addr = phi ptr [ %first, %entry ], [ %first.next, %for.inc ] | ||
%1 = load i128, ptr %first.addr, align 4 | ||
%cond2 = icmp eq i128 %1, %value | ||
br i1 %cond2, label %for.end, label %for.inc | ||
|
||
for.inc: | ||
%first.next = getelementptr inbounds i128, ptr %first.addr, i64 1 | ||
%cond3 = icmp eq ptr %first.next, %last | ||
br i1 %cond3, label %for.end, label %for.body | ||
|
||
for.end: | ||
%retval.ph = phi ptr [ %first.addr, %for.body ], [ %last, %for.inc ] | ||
br label %return | ||
|
||
return: | ||
%retval = phi ptr [ %first, %entry ], [ %retval.ph, %for.end ] | ||
ret ptr %retval | ||
} | ||
|
||
define ptr @unbound_strided_access(ptr %first, ptr %last, i32 %value) { | ||
; CHECK-LABEL: LV: Checking a loop in 'unbound_strided_access' | ||
; CHECK: LV: Not vectorizing: Loop contains strided unbound access. | ||
entry: | ||
%cond = icmp eq ptr %first, %last | ||
br i1 %cond, label %return, label %for.body | ||
|
||
for.body: | ||
%first.addr = phi ptr [ %first, %entry ], [ %first.next, %for.inc ] | ||
%1 = load i32, ptr %first.addr, align 4 | ||
%cond2 = icmp eq i32 %1, %value | ||
br i1 %cond2, label %for.end, label %for.inc | ||
|
||
for.inc: | ||
%first.next = getelementptr inbounds i32, ptr %first.addr, i64 2 | ||
%cond3 = icmp eq ptr %first.next, %last | ||
br i1 %cond3, label %for.end, label %for.body | ||
|
||
for.end: | ||
%retval.ph = phi ptr [ %first.addr, %for.body ], [ %last, %for.inc ] | ||
br label %return | ||
|
||
return: | ||
%retval = phi ptr [ %first, %entry ], [ %retval.ph, %for.end ] | ||
ret ptr %retval | ||
} | ||
|
||
define ptr @single_unbound_access(ptr %first, ptr %last, i32 %value) { | ||
arcbbb marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
; CHECK-LABEL: LV: Checking a loop in 'single_unbound_access' | ||
; CHECK: LV: We can vectorize this loop! | ||
; CHECK-NEXT: LV: Not vectorizing: Auto-vectorization of loops with speculative load is not supported. | ||
entry: | ||
%cond = icmp eq ptr %first, %last | ||
br i1 %cond, label %return, label %for.body | ||
|
||
for.body: | ||
%first.addr = phi ptr [ %first, %entry ], [ %first.next, %for.inc ] | ||
%1 = load i32, ptr %first.addr, align 4 | ||
%cond2 = icmp eq i32 %1, %value | ||
br i1 %cond2, label %for.end, label %for.inc | ||
|
||
for.inc: | ||
%first.next = getelementptr inbounds i32, ptr %first.addr, i64 1 | ||
%cond3 = icmp eq ptr %first.next, %last | ||
br i1 %cond3, label %for.end, label %for.body | ||
|
||
for.end: | ||
%retval.ph = phi ptr [ %first.addr, %for.body ], [ %last, %for.inc ] | ||
br label %return | ||
|
||
return: | ||
%retval = phi ptr [ %first, %entry ], [ %retval.ph, %for.end ] | ||
ret ptr %retval | ||
} |
arcbbb marked this conversation as resolved.
Show resolved
Hide resolved
|
Uh oh!
There was an error while loading. Please reload this page.