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 6 define void @test() { 7 ; CHECK-LABEL: define void @test( 8 entry: 9 br i1 true, label %bb1, label %bb2 10 11 bb1: 12 br label %bb3 13 ; CHECK: bb1: 14 ; CHECK-NEXT: br label %[[PH:.*]] 15 16 bb2: 17 br label %bb3 18 ; CHECK: bb2: 19 ; CHECK-NEXT: br label %[[PH]] 20 21 bb3: 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. 33 define void @test_multiple_exits_from_single_block(i8 %a, i8* %b.ptr) { 34 ; CHECK-LABEL: define void @test_multiple_exits_from_single_block( 35 entry: 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 46 loop: 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 75 exit.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 83 exit.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. 94 define void @test_pre_existing_dedicated_exits(i1 %a, i1* %ptr) { 95 ; CHECK-LABEL: define void @test_pre_existing_dedicated_exits( 96 entry: 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 101 loop.ph: 102 br label %loop.header 103 ; CHECK: loop.ph: 104 ; CHECK-NEXT: br label %loop.header 105 106 loop.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 113 loop.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 120 loop.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 127 loop.backedge: 128 br label %loop.header 129 ; CHECK: loop.backedge: 130 ; CHECK-NEXT: br label %loop.header 131 132 dedicated_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 140 dedicated_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 148 non_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. 159 define 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( 161 entry: 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 174 loop.ph: 175 br label %loop.header 176 ; CHECK: loop.ph: 177 ; CHECK-NEXT: br label %loop.header 178 179 loop.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 186 loop.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 201 loop.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 208 loop.backedge: 209 br label %loop.header 210 ; CHECK: loop.backedge: 211 ; CHECK-NEXT: br label %loop.header 212 213 exit.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 221 exit.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 229 exit.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