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