[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