aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/AMDGPU/SIAnnotateControlFlow.cpp
diff options
context:
space:
mode:
authorNicolai Haehnle <nhaehnle@gmail.com>2016-04-12 16:10:38 +0000
committerNicolai Haehnle <nhaehnle@gmail.com>2016-04-12 16:10:38 +0000
commit279970c0dc769dc24e5b66ed8fa6fcdc7653d4f4 (patch)
tree75fe7a80883d4d7bcbf3508519b27a53fe667829 /llvm/lib/Target/AMDGPU/SIAnnotateControlFlow.cpp
parent2f70584ae62056811007da1c1c89678c2c72c673 (diff)
downloadllvm-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.cpp16
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);