[PATCH] [Jump-Threading] Fixed jump threading hang issues (PR15386, PR15851)
Rafael Ávila de Espíndola
rafael.espindola at gmail.com
Tue Jun 10 06:56:23 PDT 2014
I looked a bit in a debugger and the issue is not the Changed or EverChanged variables. That part of the logic is correct. It is simply "while we found something profitable to do, do it".
What is wrong is that we can find two conflicting actions and we think they are both profitable. The testcase can be reduced to just
define void @f() {
entry:
ret void
for.cond1:
%i.025 = phi i32 [ %inc, %for.body ], [ %inc, %for.body ], [ 1, %for.cond1 ]
%cmp = icmp slt i32 %i.025, 2
br i1 %cmp, label %for.body, label %for.cond1
for.body:
%inc = add nsw i32 %i.025, 0
%a = icmp ugt i32 %inc, 2
br i1 %a, label %for.cond1, label %for.cond1
}
What happens is that we jump thread the jump from for.cond1 to itself, since we can see that the result is just a jump to for.body:
define void @f() {
entry:
ret void
for.cond1:
%i.025 = phi i32 [ %inc, %for.body ], [ %inc, %for.body ]
%cmp = icmp slt i32 %i.025, 2
br i1 %cmp, label %for.body, label %for.cond1.thread
for.cond1.thread:
br label %for.body
for.body:
%i.0252 = phi i32 [ 1, %for.cond1.thread ], [ %i.025, %for.cond1 ]
%inc = add nsw i32 %i.0252, 0
%a = icmp ugt i32 %inc, 2
br i1 %a, label %for.cond1, label %for.cond1
}
We then jump thread the jump from for.cond1.thread to for.body:
define void @f() {
entry:
ret void
for.cond1:
%i.025 = phi i32 [ %inc, %for.body ], [ %inc, %for.body ], [ 1, %for.body.thread ]
%cmp = icmp slt i32 %i.025, 2
br i1 %cmp, label %for.body, label %for.cond1.thread
for.cond1.thread:
br label %for.body.thread
for.body.thread:
br label %for.cond1
for.body:
%i.0252 = phi i32 [ %i.025, %for.cond1 ]
%inc = add nsw i32 %i.0252, 0
%a = icmp ugt i32 %inc, 2
br i1 %a, label %for.cond1, label %for.cond1
}
And we are back to a situation where for.cond1 can be jump threaded. This will loop forever, with for.cond1 and for.body alternating at giving each other another phi edge.
Now, why doesn't this happen all the time? The answer is that we don't jump thread over destinations of back edges. For example, a small modification to the test:
define void @f() {
entry:
br label %for.cond1
for.cond1:
%i.025 = phi i32 [ %inc, %for.body ], [ %inc, %for.body ], [ 1, %for.cond1 ], [ 1, %entry ]
%cmp = icmp slt i32 %i.025, 2
br i1 %cmp, label %for.body, label %for.cond1
for.body:
%inc = add nsw i32 %i.025, 0
%a = icmp ugt i32 %inc, 2
br i1 %a, label %for.cond1, label %for.cond1
}
will prevent it from going in an infinite loop since now for.cond1 is a destination of a back edge.
The logic is sound for reachable code: If we are going over the basic blocks in a loop, at some point we get to one that is pointed by a back edge and stop.
The problem is that in unreachable code there can be cycles with no back edges and we loop forever.
It seems that the best solution is to just delete dead code upfront, or at least don't try to jump thread it.
Cheers,
Rafael
http://reviews.llvm.org/D3991
More information about the llvm-commits
mailing list