1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 2; RUN: opt -S -passes=jump-threading %s | FileCheck %s 3 4; Value of predicate known on all inputs (trivial case) 5; Note: InstCombine/EarlyCSE would also get this case 6define void @test(ptr %p, ptr %addr) { 7; CHECK-LABEL: define void @test 8; CHECK-SAME: (ptr [[P:%.*]], ptr [[ADDR:%.*]]) { 9; CHECK-NEXT: entry: 10; CHECK-NEXT: [[CMP0:%.*]] = icmp eq ptr [[P]], null 11; CHECK-NEXT: br i1 [[CMP0]], label [[EXIT:%.*]], label [[LOOP:%.*]] 12; CHECK: loop: 13; CHECK-NEXT: [[P1:%.*]] = phi ptr [ [[P]], [[ENTRY:%.*]] ], [ [[P1]], [[LOOP]] ] 14; CHECK-NEXT: br label [[LOOP]] 15; CHECK: exit: 16; CHECK-NEXT: ret void 17; 18entry: 19 %cmp0 = icmp eq ptr %p, null 20 br i1 %cmp0, label %exit, label %loop 21loop: 22 %p1 = phi ptr [%p, %entry], [%p1, %loop] 23 %cmp1 = icmp eq ptr %p1, null 24 br i1 %cmp1, label %exit, label %loop 25exit: 26 ret void 27} 28 29; Value of predicate known on all inputs (non-trivial) 30define void @test2(ptr %p) { 31; CHECK-LABEL: define void @test2 32; CHECK-SAME: (ptr [[P:%.*]]) { 33; CHECK-NEXT: entry: 34; CHECK-NEXT: [[CMP0:%.*]] = icmp eq ptr [[P]], null 35; CHECK-NEXT: br i1 [[CMP0]], label [[EXIT:%.*]], label [[BACKEDGE:%.*]] 36; CHECK: backedge: 37; CHECK-NEXT: [[P1:%.*]] = phi ptr [ [[P]], [[ENTRY:%.*]] ], [ [[P2:%.*]], [[BACKEDGE]] ] 38; CHECK-NEXT: [[P2]] = load ptr, ptr [[P1]], align 8 39; CHECK-NEXT: [[CMP2:%.*]] = icmp eq ptr [[P2]], null 40; CHECK-NEXT: br i1 [[CMP2]], label [[EXIT]], label [[BACKEDGE]] 41; CHECK: exit: 42; CHECK-NEXT: ret void 43; 44entry: 45 %cmp0 = icmp eq ptr %p, null 46 br i1 %cmp0, label %exit, label %loop 47loop: 48 %p1 = phi ptr [%p, %entry], [%p2, %backedge] 49 %cmp1 = icmp eq ptr %p1, null 50 br i1 %cmp1, label %exit, label %backedge 51backedge: 52 %p2 = load ptr, ptr %p1 53 %cmp2 = icmp eq ptr %p2, null 54 br i1 %cmp2, label %exit, label %loop 55exit: 56 ret void 57} 58 59; If the inputs don't branch the same way, we can't rewrite 60; Well, we could unroll this loop exactly twice, but that's 61; a different transform. 62define void @test_mixed(ptr %p) { 63; CHECK-LABEL: define void @test_mixed 64; CHECK-SAME: (ptr [[P:%.*]]) { 65; CHECK-NEXT: entry: 66; CHECK-NEXT: [[CMP0:%.*]] = icmp eq ptr [[P]], null 67; CHECK-NEXT: br i1 [[CMP0]], label [[EXIT:%.*]], label [[LOOP:%.*]] 68; CHECK: loop: 69; CHECK-NEXT: br label [[EXIT]] 70; CHECK: exit: 71; CHECK-NEXT: ret void 72; 73entry: 74 %cmp0 = icmp eq ptr %p, null 75 br i1 %cmp0, label %exit, label %loop 76loop: 77 %p1 = phi ptr [%p, %entry], [%p1, %loop] 78 %cmp1 = icmp ne ptr %p1, null 79 br i1 %cmp1, label %exit, label %loop 80exit: 81 ret void 82} 83 84; The eq predicate is always true if we go through the path from 85; L1 to L3, no matter the phi result %t5 is on the lhs or rhs of 86; the predicate. 87declare void @goo() 88declare void @hoo() 89 90define void @test3(i32 %m, ptr %t1) { 91; CHECK-LABEL: define void @test3 92; CHECK-SAME: (i32 [[M:%.*]], ptr [[T1:%.*]]) { 93; CHECK-NEXT: L1: 94; CHECK-NEXT: [[T0:%.*]] = add i32 [[M]], 7 95; CHECK-NEXT: [[T2:%.*]] = load ptr, ptr [[T1]], align 8 96; CHECK-NEXT: [[T3:%.*]] = icmp eq ptr [[T2]], null 97; CHECK-NEXT: br i1 [[T3]], label [[L4:%.*]], label [[L3:%.*]] 98; CHECK: L3: 99; CHECK-NEXT: [[T4:%.*]] = load i32, ptr [[T2]], align 4 100; CHECK-NEXT: [[T6:%.*]] = icmp eq i32 [[T0]], [[T4]] 101; CHECK-NEXT: br i1 [[T6]], label [[L4]], label [[L5:%.*]] 102; CHECK: L4: 103; CHECK-NEXT: call void @goo() 104; CHECK-NEXT: ret void 105; CHECK: L5: 106; CHECK-NEXT: call void @hoo() 107; CHECK-NEXT: ret void 108; 109L1: 110 %t0 = add i32 %m, 7 111 %t2 = load ptr, ptr %t1, align 8 112 113 %t3 = icmp eq ptr %t2, null 114 br i1 %t3, label %L3, label %L2 115 116L2: 117 %t4 = load i32, ptr %t2, align 4 118 br label %L3 119 120L3: 121 %t5 = phi i32 [ %t0, %L1 ], [ %t4, %L2 ] 122 %t6 = icmp eq i32 %t0, %t5 123 br i1 %t6, label %L4, label %L5 124 125L4: 126 call void @goo() 127 ret void 128 129L5: 130 call void @hoo() 131 ret void 132} 133