1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -jump-threading < %s | FileCheck %s 3 4; Check that the heuristic for avoiding accidental introduction of irreducible 5; loops doesn't also prevent us from threading simple constructs where this 6; isn't a problem. 7 8declare void @opaque_body() 9 10define void @jump_threading_loopheader() { 11; CHECK-LABEL: @jump_threading_loopheader( 12; CHECK-NEXT: top: 13; CHECK-NEXT: br label [[ENTRY:%.*]] 14; CHECK: entry: 15; CHECK-NEXT: [[IND:%.*]] = phi i32 [ 0, [[TOP:%.*]] ], [ [[NEXTIND:%.*]], [[LATCH:%.*]] ] 16; CHECK-NEXT: [[NEXTIND]] = add i32 [[IND]], 1 17; CHECK-NEXT: [[CMP:%.*]] = icmp ule i32 [[IND]], 10 18; CHECK-NEXT: br i1 [[CMP]], label [[LATCH]], label [[EXIT:%.*]] 19; CHECK: latch: 20; CHECK-NEXT: call void @opaque_body() 21; CHECK-NEXT: br label [[ENTRY]] 22; CHECK: exit: 23; CHECK-NEXT: ret void 24; 25top: 26 br label %entry 27 28entry: 29 %ind = phi i32 [0, %top], [%nextind, %latch] 30 %nextind = add i32 %ind, 1 31 %cmp = icmp ule i32 %ind, 10 32 br i1 %cmp, label %body, label %latch 33 34body: 35 call void @opaque_body() 36 br label %latch 37 38latch: 39 %cond = phi i2 [1, %entry], [2, %body] 40 switch i2 %cond, label %unreach [ 41 i2 2, label %entry 42 i2 1, label %exit 43 ] 44 45unreach: 46 unreachable 47 48exit: 49 ret void 50} 51 52; We also need to check the opposite order of the branches, in the switch 53; instruction because jump-threading relies on that to decide which edge to 54; try to thread first. 55define void @jump_threading_loopheader2() { 56; CHECK-LABEL: @jump_threading_loopheader2( 57; CHECK-NEXT: top: 58; CHECK-NEXT: br label [[ENTRY:%.*]] 59; CHECK: entry: 60; CHECK-NEXT: [[IND:%.*]] = phi i32 [ 0, [[TOP:%.*]] ], [ [[NEXTIND:%.*]], [[LATCH:%.*]] ] 61; CHECK-NEXT: [[NEXTIND]] = add i32 [[IND]], 1 62; CHECK-NEXT: [[CMP:%.*]] = icmp ule i32 [[IND]], 10 63; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LATCH]] 64; CHECK: latch: 65; CHECK-NEXT: br label [[ENTRY]] 66; CHECK: exit: 67; CHECK-NEXT: call void @opaque_body() 68; CHECK-NEXT: ret void 69; 70top: 71 br label %entry 72 73entry: 74 %ind = phi i32 [0, %top], [%nextind, %latch] 75 %nextind = add i32 %ind, 1 76 %cmp = icmp ule i32 %ind, 10 77 br i1 %cmp, label %body, label %latch 78 79body: 80 call void @opaque_body() 81 br label %latch 82 83latch: 84 %cond = phi i2 [1, %entry], [2, %body] 85 switch i2 %cond, label %unreach [ 86 i2 1, label %entry 87 i2 2, label %exit 88 ] 89 90unreach: 91 unreachable 92 93exit: 94 ret void 95} 96 97; Check if we can handle undef branch condition. 98define void @jump_threading_loopheader3() { 99; CHECK-LABEL: @jump_threading_loopheader3( 100; CHECK-NEXT: top: 101; CHECK-NEXT: br label [[ENTRY:%.*]] 102; CHECK: entry: 103; CHECK-NEXT: [[IND:%.*]] = phi i32 [ 0, [[TOP:%.*]] ], [ [[NEXTIND:%.*]], [[LATCH:%.*]] ] 104; CHECK-NEXT: [[NEXTIND]] = add i32 [[IND]], 1 105; CHECK-NEXT: [[CMP:%.*]] = icmp ule i32 [[IND]], 10 106; CHECK-NEXT: br i1 [[CMP]], label [[LATCH]], label [[EXIT:%.*]] 107; CHECK: latch: 108; CHECK-NEXT: call void @opaque_body() 109; CHECK-NEXT: br label [[ENTRY]] 110; CHECK: exit: 111; CHECK-NEXT: ret void 112; 113top: 114 br label %entry 115 116entry: 117 %ind = phi i32 [0, %top], [%nextind, %latch] 118 %nextind = add i32 %ind, 1 119 %cmp = icmp ule i32 %ind, 10 120 br i1 %cmp, label %body, label %latch 121 122body: 123 call void @opaque_body() 124 br label %latch 125 126latch: 127 %phi = phi i32 [undef, %entry], [0, %body] 128 %cmp1 = icmp eq i32 %phi, 0 129 br i1 %cmp1, label %entry, label %exit 130 131exit: 132 ret void 133} 134