Skip to content

Commit f5315f8

Browse files
committed
Limit to single unbound access. Add tests
1 parent 78f05df commit f5315f8

File tree

2 files changed

+97
-7
lines changed

2 files changed

+97
-7
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1777,15 +1777,9 @@ bool LoopVectorizationLegality::isVectorizableEarlyExitLoop() {
17771777
}
17781778
// Speculative loads need to be unit-stride.
17791779
for (LoadInst *LI : NonDerefLoads) {
1780-
if (LI->getParent() != TheLoop->getHeader()) {
1781-
reportVectorizationFailure("Cannot vectorize predicated speculative load",
1782-
"SpeculativeLoadNeedsPredication", ORE,
1783-
TheLoop);
1784-
return false;
1785-
}
17861780
int Stride = isConsecutivePtr(LI->getType(), LI->getPointerOperand());
17871781
if (Stride != 1) {
1788-
reportVectorizationFailure("Loop contains non-unit-stride load",
1782+
reportVectorizationFailure("Loop contains strided unbound access",
17891783
"Cannot vectorize early exit loop with "
17901784
"speculative non-unit-stride load",
17911785
"SpeculativeNonUnitStrideLoadEarlyExitLoop",
@@ -1795,6 +1789,13 @@ bool LoopVectorizationLegality::isVectorizableEarlyExitLoop() {
17951789
SpeculativeLoads.insert(LI);
17961790
LLVM_DEBUG(dbgs() << "LV: Found speculative load: " << *LI << "\n");
17971791
}
1792+
// Support single Speculative load for now.
1793+
if (NonDerefLoads.size() > 1) {
1794+
reportVectorizationFailure("Loop contains more than one unbound access",
1795+
"TooManySpeculativeLoadInEarlyExitLoop",
1796+
ORE, TheLoop);
1797+
return false;
1798+
}
17981799

17991800
[[maybe_unused]] const SCEV *SymbolicMaxBTC =
18001801
PSE.getSymbolicMaxBackedgeTakenCount();
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
; REQUIRES: asserts
2+
; RUN: opt -passes=loop-vectorize -debug-only=loop-vectorize -disable-output 2>&1 -mtriple=riscv64 -mattr=+v -S %s | FileCheck %s
3+
4+
define ptr @two_unbound_access(ptr %first, ptr %last, ptr %addr2) {
5+
; CHECK-LABEL: LV: Checking a loop in 'two_unbound_access'
6+
; CHECK: LV: Not vectorizing: Loop contains more than one unbound access.
7+
entry:
8+
%cond = icmp eq ptr %first, %last
9+
br i1 %cond, label %return, label %for.body
10+
11+
for.body:
12+
%first.addr = phi ptr [ %first, %entry], [ %first.next, %for.inc ]
13+
%match.addr = phi ptr [ %addr2, %entry ], [ %match.next, %for.inc ]
14+
%1 = load i32, ptr %first.addr, align 4
15+
%match.value = load i32, ptr %match.addr, align 4
16+
%cmp1 = icmp eq i32 %1, %match.value
17+
br i1 %cmp1, label %early.exit, label %for.inc
18+
19+
for.inc:
20+
%match.next = getelementptr inbounds nuw i8, ptr %match.addr, i64 4
21+
%first.next = getelementptr inbounds i8, ptr %first.addr, i64 4
22+
%exit = icmp eq ptr %first.next, %last
23+
br i1 %exit, label %main.exit, label %for.body
24+
25+
early.exit:
26+
br label %return
27+
28+
main.exit:
29+
br label %return
30+
31+
return:
32+
%retval = phi ptr [ %first, %entry ], [ %last, %main.exit ], [ %first.addr, %early.exit ]
33+
ret ptr %retval
34+
}
35+
36+
define ptr @unbound_strided_access(ptr %first, ptr %last, i32 %value) {
37+
; CHECK-LABEL: LV: Checking a loop in 'unbound_strided_access'
38+
; CHECK: LV: Not vectorizing: Loop contains strided unbound access.
39+
entry:
40+
%cond = icmp eq ptr %first, %last
41+
br i1 %cond, label %return, label %for.body
42+
43+
for.body:
44+
%first.addr = phi ptr [ %first, %entry ], [ %first.next, %for.inc ]
45+
%1 = load i32, ptr %first.addr, align 4
46+
%cond2= icmp eq i32 %1, %value
47+
br i1 %cond2, label %for.end, label %for.inc
48+
49+
for.inc:
50+
%first.next = getelementptr inbounds i32, ptr %first.addr, i64 2
51+
%cond3 = icmp eq ptr %first.next, %last
52+
br i1 %cond3, label %for.end, label %for.body
53+
54+
for.end:
55+
%retval.ph = phi ptr [ %first.addr, %for.body ], [ %last, %for.inc ]
56+
br label %return
57+
58+
return:
59+
%retval = phi ptr [ %first, %entry ], [ %retval.ph, %for.end ]
60+
ret ptr %retval
61+
}
62+
63+
define ptr @single_unbound_access(ptr %first, ptr %last, i32 %value) {
64+
; CHECK-LABEL: LV: Checking a loop in 'single_unbound_access'
65+
; CHECK: LV: We can vectorize this loop!
66+
; CHECK-NEXT: LV: Not vectorizing: Auto-vectorization of loops with speculative load is not supported.
67+
entry:
68+
%cond = icmp eq ptr %first, %last
69+
br i1 %cond, label %return, label %for.body
70+
71+
for.body:
72+
%first.addr = phi ptr [ %first, %entry ], [ %first.next, %for.inc ]
73+
%1 = load i32, ptr %first.addr, align 4
74+
%cond2= icmp eq i32 %1, %value
75+
br i1 %cond2, label %for.end, label %for.inc
76+
77+
for.inc:
78+
%first.next = getelementptr inbounds i32, ptr %first.addr, i64 1
79+
%cond3 = icmp eq ptr %first.next, %last
80+
br i1 %cond3, label %for.end, label %for.body
81+
82+
for.end:
83+
%retval.ph = phi ptr [ %first.addr, %for.body ], [ %last, %for.inc ]
84+
br label %return
85+
86+
return:
87+
%retval = phi ptr [ %first, %entry ], [ %retval.ph, %for.end ]
88+
ret ptr %retval
89+
}

0 commit comments

Comments
 (0)