[LoopUnroll] Respect the convergent attribute.
Summary:
Specifically, when we perform runtime loop unrolling of a loop that
contains a convergent op, we can only unroll k times, where k divides
the loop trip multiple.
Without this change, we'll happily unroll e.g. the following loop
for (int i = 0; i < N; ++i) {
if (i == 0) convergent_op();
foo();
}
into
int i = 0;
if (N % 2 == 1) {
convergent_op();
foo();
++i;
}
for (; i < N - 1; i += 2) {
if (i == 0) convergent_op();
foo();
foo();
}.
This is unsafe, because we've just added a control-flow dependency to
the convergent op in the prelude.
In general, runtime unrolling loops that contain convergent ops is safe
only if we don't have emit a prelude, which occurs when the unroll count
divides the trip multiple.
Reviewers: resistor
Subscribers: llvm-commits, mzolotukhin
Differential Revision: http://reviews.llvm.org/D17526
llvm-svn: 263509
This commit is contained in:
@@ -273,7 +273,23 @@ bool llvm::UnrollLoop(Loop *L, unsigned Count, unsigned TripCount,
|
||||
// flag is specified.
|
||||
bool RuntimeTripCount = (TripCount == 0 && Count > 0 && AllowRuntime);
|
||||
|
||||
if (RuntimeTripCount &&
|
||||
// Loops containing convergent instructions must have a count that divides
|
||||
// their TripMultiple.
|
||||
DEBUG(
|
||||
bool HasConvergent = false;
|
||||
for (auto &BB : L->blocks())
|
||||
for (auto &I : *BB)
|
||||
if (auto CS = CallSite(&I))
|
||||
HasConvergent |= CS.isConvergent();
|
||||
assert(
|
||||
!HasConvergent || TripMultiple % Count == 0 &&
|
||||
"Unroll count must divide trip multiple if loop contains a convergent "
|
||||
"operation.");
|
||||
);
|
||||
// Don't output the runtime loop prolog if Count is a multiple of
|
||||
// TripMultiple. Such a prolog is never needed, and is unsafe if the loop
|
||||
// contains a convergent instruction.
|
||||
if (RuntimeTripCount && TripMultiple % Count != 0 &&
|
||||
!UnrollRuntimeLoopProlog(L, Count, AllowExpensiveTripCount, LI, SE, DT,
|
||||
PreserveLCSSA))
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user