diff options
author | Sameer Sahasrabuddhe <sameer.sahasrabuddhe@amd.com> | 2020-05-19 09:22:08 +0530 |
---|---|---|
committer | Sameer Sahasrabuddhe <sameer.sahasrabuddhe@amd.com> | 2020-05-19 09:22:39 +0530 |
commit | 6c8488436644af41b3e29564ff85dc5eaa240347 (patch) | |
tree | 24326f09ccdfbf1d9c92c2aebcbf97c1ed39a582 /llvm/lib/Transforms/Utils/LoopSimplify.cpp | |
parent | a6be4d17e349f834e4d365f68e0435a1c4334a81 (diff) | |
download | llvm-6c8488436644af41b3e29564ff85dc5eaa240347.zip llvm-6c8488436644af41b3e29564ff85dc5eaa240347.tar.gz llvm-6c8488436644af41b3e29564ff85dc5eaa240347.tar.bz2 |
[LoopSimplify] don't separate nested loops with convergent calls
Summary:
When a loop has multiple backedges, loop simplification attempts to
separate them out into nested loops. This results in incorrect control
flow in the presence of some functions like a GPU barrier. This change
skips the transformation when such "convergent" function calls are
present in the loop body.
Reviewed By: nhaehnle
Differential Revision: https://reviews.llvm.org/D80078
Diffstat (limited to 'llvm/lib/Transforms/Utils/LoopSimplify.cpp')
-rw-r--r-- | llvm/lib/Transforms/Utils/LoopSimplify.cpp | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/Utils/LoopSimplify.cpp b/llvm/lib/Transforms/Utils/LoopSimplify.cpp index 28f88f3..14c6950 100644 --- a/llvm/lib/Transforms/Utils/LoopSimplify.cpp +++ b/llvm/lib/Transforms/Utils/LoopSimplify.cpp @@ -230,6 +230,27 @@ static Loop *separateNestedLoop(Loop *L, BasicBlock *Preheader, if (!Preheader) return nullptr; + // Treat the presence of convergent functions conservatively. The + // transformation is invalid if calls to certain convergent + // functions (like an AMDGPU barrier) get included in the resulting + // inner loop. But blocks meant for the inner loop will be + // identified later at a point where it's too late to abort the + // transformation. Also, the convergent attribute is not really + // sufficient to express the semantics of functions that are + // affected by this transformation. So we choose to back off if such + // a function call is present until a better alternative becomes + // available. This is similar to the conservative treatment of + // convergent function calls in GVNHoist and JumpThreading. + for (auto BB : L->blocks()) { + for (auto &II : *BB) { + if (auto CI = dyn_cast<CallBase>(&II)) { + if (CI->isConvergent()) { + return nullptr; + } + } + } + } + // The header is not a landing pad; preheader insertion should ensure this. BasicBlock *Header = L->getHeader(); assert(!Header->isEHPad() && "Can't insert backedge to EH pad"); |