diff options
author | Nicolai Haehnle <nhaehnle@gmail.com> | 2016-04-12 16:10:38 +0000 |
---|---|---|
committer | Nicolai Haehnle <nhaehnle@gmail.com> | 2016-04-12 16:10:38 +0000 |
commit | 279970c0dc769dc24e5b66ed8fa6fcdc7653d4f4 (patch) | |
tree | 75fe7a80883d4d7bcbf3508519b27a53fe667829 /llvm/lib/Target/AMDGPU/SIAnnotateControlFlow.cpp | |
parent | 2f70584ae62056811007da1c1c89678c2c72c673 (diff) | |
download | llvm-279970c0dc769dc24e5b66ed8fa6fcdc7653d4f4.zip llvm-279970c0dc769dc24e5b66ed8fa6fcdc7653d4f4.tar.gz llvm-279970c0dc769dc24e5b66ed8fa6fcdc7653d4f4.tar.bz2 |
AMDGPU/SI: Fix a mis-compilation of multi-level breaks
Summary:
Under certain circumstances, multi-level breaks (or what is understood by
the control flow passes as such) could be miscompiled in a way that causes
infinite loops, by emitting incorrect control flow intrinsics.
This fixes a hang in
dEQP-GLES3.functional.shaders.loops.while_dynamic_iterations.conditional_continue_vertex
Reviewers: arsenm, tstellarAMD
Subscribers: arsenm, llvm-commits
Differential Revision: http://reviews.llvm.org/D18967
llvm-svn: 266088
Diffstat (limited to 'llvm/lib/Target/AMDGPU/SIAnnotateControlFlow.cpp')
-rw-r--r-- | llvm/lib/Target/AMDGPU/SIAnnotateControlFlow.cpp | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/llvm/lib/Target/AMDGPU/SIAnnotateControlFlow.cpp b/llvm/lib/Target/AMDGPU/SIAnnotateControlFlow.cpp index 92a178b..563beba 100644 --- a/llvm/lib/Target/AMDGPU/SIAnnotateControlFlow.cpp +++ b/llvm/lib/Target/AMDGPU/SIAnnotateControlFlow.cpp @@ -262,7 +262,23 @@ Value *SIAnnotateControlFlow::handleLoopCondition(Value *Cond, PHINode *Broken, BasicBlock *From = Phi->getIncomingBlock(i); if (From == IDom) { + // We're in the following situation: + // IDom/From + // | \ + // | If-block + // | / + // Parent + // where we want to break out of the loop if the If-block is not taken. + // Due to the depth-first traversal, there should be an end.cf + // intrinsic in Parent, and we insert an else.break before it. + // + // Note that the end.cf need not be the first non-phi instruction + // of parent, particularly when we're dealing with a multi-level + // break, but it should occur within a group of intrinsic calls + // at the beginning of the block. CallInst *OldEnd = dyn_cast<CallInst>(Parent->getFirstInsertionPt()); + while (OldEnd && OldEnd->getCalledFunction() != EndCf) + OldEnd = dyn_cast<CallInst>(OldEnd->getNextNode()); if (OldEnd && OldEnd->getCalledFunction() == EndCf) { Value *Args[] = { OldEnd->getArgOperand(0), NewPhi }; Ret = CallInst::Create(ElseBreak, Args, "", OldEnd); |