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