| ; RUN: opt -jump-threading -S < %s | FileCheck %s | 
 |  | 
 | declare void @side_effect(i32) | 
 |  | 
 | define void @test0(i32 %i, i32 %len) { | 
 | ; CHECK-LABEL: @test0( | 
 |  entry: | 
 |   call void @side_effect(i32 0) | 
 |   %i.inc = add nuw i32 %i, 1 | 
 |   %c0 = icmp ult i32 %i.inc, %len | 
 |   br i1 %c0, label %left, label %right | 
 |  | 
 |  left: | 
 | ; CHECK: entry: | 
 | ; CHECK: br i1 %c0, label %left0, label %right | 
 |  | 
 | ; CHECK: left0: | 
 | ; CHECK: call void @side_effect | 
 | ; CHECK-NOT: br i1 %c1 | 
 | ; CHECK: call void @side_effect | 
 |   call void @side_effect(i32 0) | 
 |   %c1 = icmp ult i32 %i, %len | 
 |   br i1 %c1, label %left0, label %right | 
 |  | 
 |  left0: | 
 |   call void @side_effect(i32 0) | 
 |   ret void | 
 |  | 
 |  right: | 
 |   %t = phi i32 [ 1, %left ], [ 2, %entry ] | 
 |   call void @side_effect(i32 %t) | 
 |   ret void | 
 | } | 
 |  | 
 | define void @test1(i32 %i, i32 %len) { | 
 | ; CHECK-LABEL: @test1( | 
 |  entry: | 
 |   call void @side_effect(i32 0) | 
 |   %i.inc = add nsw i32 %i, 1 | 
 |   %c0 = icmp slt i32 %i.inc, %len | 
 |   br i1 %c0, label %left, label %right | 
 |  | 
 |  left: | 
 | ; CHECK: entry: | 
 | ; CHECK: br i1 %c0, label %left0, label %right | 
 |  | 
 | ; CHECK: left0: | 
 | ; CHECK: call void @side_effect | 
 | ; CHECK-NOT: br i1 %c1 | 
 | ; CHECK: call void @side_effect | 
 |   call void @side_effect(i32 0) | 
 |   %c1 = icmp slt i32 %i, %len | 
 |   br i1 %c1, label %left0, label %right | 
 |  | 
 |  left0: | 
 |   call void @side_effect(i32 0) | 
 |   ret void | 
 |  | 
 |  right: | 
 |   %t = phi i32 [ 1, %left ], [ 2, %entry ] | 
 |   call void @side_effect(i32 %t) | 
 |   ret void | 
 | } | 
 |  | 
 | define void @test2(i32 %i, i32 %len, i1* %c.ptr) { | 
 | ; CHECK-LABEL: @test2( | 
 |  | 
 | ; CHECK: entry: | 
 | ; CHECK: br i1 %c0, label %cont, label %right | 
 | ; CHECK: cont: | 
 | ; CHECK: br i1 %c, label %left0, label %right | 
 | ; CHECK: left0: | 
 | ; CHECK: call void @side_effect(i32 0) | 
 | ; CHECK: call void @side_effect(i32 0) | 
 |  entry: | 
 |   call void @side_effect(i32 0) | 
 |   %i.inc = add nsw i32 %i, 1 | 
 |   %c0 = icmp slt i32 %i.inc, %len | 
 |   br i1 %c0, label %cont, label %right | 
 |  | 
 |  cont: | 
 |   %c = load i1, i1* %c.ptr | 
 |   br i1 %c, label %left, label %right | 
 |  | 
 |  left: | 
 |   call void @side_effect(i32 0) | 
 |   %c1 = icmp slt i32 %i, %len | 
 |   br i1 %c1, label %left0, label %right | 
 |  | 
 |  left0: | 
 |   call void @side_effect(i32 0) | 
 |   ret void | 
 |  | 
 |  right: | 
 |   %t = phi i32 [ 1, %left ], [ 2, %entry ], [ 3, %cont ] | 
 |   call void @side_effect(i32 %t) | 
 |   ret void | 
 | } | 
 |  | 
 | ; A s<= B implies A s> B is false. | 
 | ; CHECK-LABEL: @test3( | 
 | ; CHECK: entry: | 
 | ; CHECK: br i1 %cmp, label %if.end, label %if.end3 | 
 | ; CHECK-NOT: br i1 %cmp1, label %if.then2, label %if.end | 
 | ; CHECK-NOT: call void @side_effect(i32 0) | 
 | ; CHECK: br label %if.end3 | 
 | ; CHECK: ret void | 
 |  | 
 | define void @test3(i32 %a, i32 %b) { | 
 | entry: | 
 |   %cmp = icmp sle i32 %a, %b | 
 |   br i1 %cmp, label %if.then, label %if.end3 | 
 |  | 
 | if.then: | 
 |   %cmp1 = icmp sgt i32 %a, %b | 
 |   br i1 %cmp1, label %if.then2, label %if.end | 
 |  | 
 | if.then2: | 
 |   call void @side_effect(i32 0) | 
 |   br label %if.end | 
 |  | 
 | if.end: | 
 |   br label %if.end3 | 
 |  | 
 | if.end3: | 
 |   ret void | 
 | } | 
 |  | 
 | declare void @is(i1) | 
 |  | 
 | ; If A >=s B is false then A <=s B is implied true. | 
 | ; CHECK-LABEL: @test_sge_sle | 
 | ; CHECK: call void @is(i1 true) | 
 | ; CHECK-NOT: call void @is(i1 false) | 
 | define void @test_sge_sle(i32 %a, i32 %b) { | 
 |   %cmp1 = icmp sge i32 %a, %b | 
 |   br i1 %cmp1, label %untaken, label %taken | 
 |  | 
 | taken: | 
 |   %cmp2 = icmp sle i32 %a, %b | 
 |   br i1 %cmp2, label %istrue, label %isfalse | 
 |  | 
 | istrue: | 
 |   call void @is(i1 true) | 
 |   ret void | 
 |  | 
 | isfalse: | 
 |   call void @is(i1 false) | 
 |   ret void | 
 |  | 
 | untaken: | 
 |   ret void | 
 | } | 
 |  | 
 | ; If A <=s B is false then A <=s B is implied false. | 
 | ; CHECK-LABEL: @test_sle_sle | 
 | ; CHECK-NOT: call void @is(i1 true) | 
 | ; CHECK: call void @is(i1 false) | 
 | define void @test_sle_sle(i32 %a, i32 %b) { | 
 |   %cmp1 = icmp sle i32 %a, %b | 
 |   br i1 %cmp1, label %untaken, label %taken | 
 |  | 
 | taken: | 
 |   %cmp2 = icmp sle i32 %a, %b | 
 |   br i1 %cmp2, label %istrue, label %isfalse | 
 |  | 
 | istrue: | 
 |   call void @is(i1 true) | 
 |   ret void | 
 |  | 
 | isfalse: | 
 |   call void @is(i1 false) | 
 |   ret void | 
 |  | 
 | untaken: | 
 |   ret void | 
 | } |