1; RUN: opt < %s -S -loop-simplify | FileCheck %s 2; RUN: opt < %s -S -passes=loop-simplify | FileCheck %s 3 4; This function should get a preheader inserted before bb3, that is jumped 5; to by bb1 & bb2 6define void @test() { 7; CHECK-LABEL: define void @test( 8entry: 9 br i1 true, label %bb1, label %bb2 10 11bb1: 12 br label %bb3 13; CHECK: bb1: 14; CHECK-NEXT: br label %[[PH:.*]] 15 16bb2: 17 br label %bb3 18; CHECK: bb2: 19; CHECK-NEXT: br label %[[PH]] 20 21bb3: 22 br label %bb3 23; CHECK: [[PH]]: 24; CHECK-NEXT: br label %bb3 25; 26; CHECK: bb3: 27; CHECK-NEXT: br label %bb3 28} 29 30; Test a case where we have multiple exit blocks as successors of a single loop 31; block that need to be made dedicated exit blocks. We also have multiple 32; exiting edges to one of the exit blocks that all should be rewritten. 33define void @test_multiple_exits_from_single_block(i8 %a, i8* %b.ptr) { 34; CHECK-LABEL: define void @test_multiple_exits_from_single_block( 35entry: 36 switch i8 %a, label %loop [ 37 i8 0, label %exit.a 38 i8 1, label %exit.b 39 ] 40; CHECK: entry: 41; CHECK-NEXT: switch i8 %a, label %[[PH:.*]] [ 42; CHECK-NEXT: i8 0, label %exit.a 43; CHECK-NEXT: i8 1, label %exit.b 44; CHECK-NEXT: ] 45 46loop: 47 %b = load volatile i8, i8* %b.ptr 48 switch i8 %b, label %loop [ 49 i8 0, label %exit.a 50 i8 1, label %exit.b 51 i8 2, label %loop 52 i8 3, label %exit.a 53 i8 4, label %loop 54 i8 5, label %exit.a 55 i8 6, label %loop 56 ] 57; CHECK: [[PH]]: 58; CHECK-NEXT: br label %loop 59; 60; CHECK: loop: 61; CHECK-NEXT: %[[B:.*]] = load volatile i8, i8* %b.ptr 62; CHECK-NEXT: switch i8 %[[B]], label %[[BACKEDGE:.*]] [ 63; CHECK-NEXT: i8 0, label %[[LOOPEXIT_A:.*]] 64; CHECK-NEXT: i8 1, label %[[LOOPEXIT_B:.*]] 65; CHECK-NEXT: i8 2, label %[[BACKEDGE]] 66; CHECK-NEXT: i8 3, label %[[LOOPEXIT_A]] 67; CHECK-NEXT: i8 4, label %[[BACKEDGE]] 68; CHECK-NEXT: i8 5, label %[[LOOPEXIT_A]] 69; CHECK-NEXT: i8 6, label %[[BACKEDGE]] 70; CHECK-NEXT: ] 71; 72; CHECK: [[BACKEDGE]]: 73; CHECK-NEXT: br label %loop 74 75exit.a: 76 ret void 77; CHECK: [[LOOPEXIT_A]]: 78; CHECK-NEXT: br label %exit.a 79; 80; CHECK: exit.a: 81; CHECK-NEXT: ret void 82 83exit.b: 84 ret void 85; CHECK: [[LOOPEXIT_B]]: 86; CHECK-NEXT: br label %exit.b 87; 88; CHECK: exit.b: 89; CHECK-NEXT: ret void 90} 91 92; Check that we leave already dedicated exits alone when forming dedicated exit 93; blocks. 94define void @test_pre_existing_dedicated_exits(i1 %a, i1* %ptr) { 95; CHECK-LABEL: define void @test_pre_existing_dedicated_exits( 96entry: 97 br i1 %a, label %loop.ph, label %non_dedicated_exit 98; CHECK: entry: 99; CHECK-NEXT: br i1 %a, label %loop.ph, label %non_dedicated_exit 100 101loop.ph: 102 br label %loop.header 103; CHECK: loop.ph: 104; CHECK-NEXT: br label %loop.header 105 106loop.header: 107 %c1 = load volatile i1, i1* %ptr 108 br i1 %c1, label %loop.body1, label %dedicated_exit1 109; CHECK: loop.header: 110; CHECK-NEXT: %[[C1:.*]] = load volatile i1, i1* %ptr 111; CHECK-NEXT: br i1 %[[C1]], label %loop.body1, label %dedicated_exit1 112 113loop.body1: 114 %c2 = load volatile i1, i1* %ptr 115 br i1 %c2, label %loop.body2, label %non_dedicated_exit 116; CHECK: loop.body1: 117; CHECK-NEXT: %[[C2:.*]] = load volatile i1, i1* %ptr 118; CHECK-NEXT: br i1 %[[C2]], label %loop.body2, label %[[LOOPEXIT:.*]] 119 120loop.body2: 121 %c3 = load volatile i1, i1* %ptr 122 br i1 %c3, label %loop.backedge, label %dedicated_exit2 123; CHECK: loop.body2: 124; CHECK-NEXT: %[[C3:.*]] = load volatile i1, i1* %ptr 125; CHECK-NEXT: br i1 %[[C3]], label %loop.backedge, label %dedicated_exit2 126 127loop.backedge: 128 br label %loop.header 129; CHECK: loop.backedge: 130; CHECK-NEXT: br label %loop.header 131 132dedicated_exit1: 133 ret void 134; Check that there isn't a split loop exit. 135; CHECK-NOT: br label %dedicated_exit1 136; 137; CHECK: dedicated_exit1: 138; CHECK-NEXT: ret void 139 140dedicated_exit2: 141 ret void 142; Check that there isn't a split loop exit. 143; CHECK-NOT: br label %dedicated_exit2 144; 145; CHECK: dedicated_exit2: 146; CHECK-NEXT: ret void 147 148non_dedicated_exit: 149 ret void 150; CHECK: [[LOOPEXIT]]: 151; CHECK-NEXT: br label %non_dedicated_exit 152; 153; CHECK: non_dedicated_exit: 154; CHECK-NEXT: ret void 155} 156 157; Check that we form what dedicated exits we can even when some exits are 158; reached via indirectbr which precludes forming dedicated exits. 159define void @test_form_some_dedicated_exits_despite_indirectbr(i8 %a, i8* %ptr, i8** %addr.ptr) { 160; CHECK-LABEL: define void @test_form_some_dedicated_exits_despite_indirectbr( 161entry: 162 switch i8 %a, label %loop.ph [ 163 i8 0, label %exit.a 164 i8 1, label %exit.b 165 i8 2, label %exit.c 166 ] 167; CHECK: entry: 168; CHECK-NEXT: switch i8 %a, label %loop.ph [ 169; CHECK-NEXT: i8 0, label %exit.a 170; CHECK-NEXT: i8 1, label %exit.b 171; CHECK-NEXT: i8 2, label %exit.c 172; CHECK-NEXT: ] 173 174loop.ph: 175 br label %loop.header 176; CHECK: loop.ph: 177; CHECK-NEXT: br label %loop.header 178 179loop.header: 180 %addr1 = load volatile i8*, i8** %addr.ptr 181 indirectbr i8* %addr1, [label %loop.body1, label %exit.a] 182; CHECK: loop.header: 183; CHECK-NEXT: %[[ADDR1:.*]] = load volatile i8*, i8** %addr.ptr 184; CHECK-NEXT: indirectbr i8* %[[ADDR1]], [label %loop.body1, label %exit.a] 185 186loop.body1: 187 %b = load volatile i8, i8* %ptr 188 switch i8 %b, label %loop.body2 [ 189 i8 0, label %exit.a 190 i8 1, label %exit.b 191 i8 2, label %exit.c 192 ] 193; CHECK: loop.body1: 194; CHECK-NEXT: %[[B:.*]] = load volatile i8, i8* %ptr 195; CHECK-NEXT: switch i8 %[[B]], label %loop.body2 [ 196; CHECK-NEXT: i8 0, label %exit.a 197; CHECK-NEXT: i8 1, label %[[LOOPEXIT:.*]] 198; CHECK-NEXT: i8 2, label %exit.c 199; CHECK-NEXT: ] 200 201loop.body2: 202 %addr2 = load volatile i8*, i8** %addr.ptr 203 indirectbr i8* %addr2, [label %loop.backedge, label %exit.c] 204; CHECK: loop.body2: 205; CHECK-NEXT: %[[ADDR2:.*]] = load volatile i8*, i8** %addr.ptr 206; CHECK-NEXT: indirectbr i8* %[[ADDR2]], [label %loop.backedge, label %exit.c] 207 208loop.backedge: 209 br label %loop.header 210; CHECK: loop.backedge: 211; CHECK-NEXT: br label %loop.header 212 213exit.a: 214 ret void 215; Check that there isn't a split loop exit. 216; CHECK-NOT: br label %exit.a 217; 218; CHECK: exit.a: 219; CHECK-NEXT: ret void 220 221exit.b: 222 ret void 223; CHECK: [[LOOPEXIT]]: 224; CHECK-NEXT: br label %exit.b 225; 226; CHECK: exit.b: 227; CHECK-NEXT: ret void 228 229exit.c: 230 ret void 231; Check that there isn't a split loop exit. 232; CHECK-NOT: br label %exit.c 233; 234; CHECK: exit.c: 235; CHECK-NEXT: ret void 236} 237