1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2 ; RUN: opt < %s -S -loop-unroll -verify-dom-info | FileCheck %s 3 4 declare void @f1() 5 declare void @f2() 6 7 ; Check that we can peel off iterations that make conditions true. 8 define void @test1(i32 %k) { 9 ; CHECK-LABEL: @test1( 10 ; CHECK-NEXT: for.body.lr.ph: 11 ; CHECK-NEXT: br label [[FOR_BODY_PEEL_BEGIN:%.*]] 12 ; CHECK: for.body.peel.begin: 13 ; CHECK-NEXT: br label [[FOR_BODY_PEEL:%.*]] 14 ; CHECK: for.body.peel: 15 ; CHECK-NEXT: [[CMP1_PEEL:%.*]] = icmp ult i32 0, 2 16 ; CHECK-NEXT: br i1 [[CMP1_PEEL]], label [[IF_THEN_PEEL:%.*]], label [[IF_ELSE_PEEL:%.*]] 17 ; CHECK: if.else.peel: 18 ; CHECK-NEXT: call void @f2() 19 ; CHECK-NEXT: br label [[FOR_INC_PEEL:%.*]] 20 ; CHECK: if.then.peel: 21 ; CHECK-NEXT: call void @f1() 22 ; CHECK-NEXT: br label [[FOR_INC_PEEL]] 23 ; CHECK: for.inc.peel: 24 ; CHECK-NEXT: [[INC_PEEL:%.*]] = add nsw i32 0, 1 25 ; CHECK-NEXT: [[CMP_PEEL:%.*]] = icmp slt i32 [[INC_PEEL]], [[K:%.*]] 26 ; CHECK-NEXT: br i1 [[CMP_PEEL]], label [[FOR_BODY_PEEL_NEXT:%.*]], label [[FOR_END:%.*]] 27 ; CHECK: for.body.peel.next: 28 ; CHECK-NEXT: br label [[FOR_BODY_PEEL2:%.*]] 29 ; CHECK: for.body.peel2: 30 ; CHECK-NEXT: [[CMP1_PEEL3:%.*]] = icmp ult i32 [[INC_PEEL]], 2 31 ; CHECK-NEXT: br i1 [[CMP1_PEEL3]], label [[IF_THEN_PEEL5:%.*]], label [[IF_ELSE_PEEL4:%.*]] 32 ; CHECK: if.else.peel4: 33 ; CHECK-NEXT: call void @f2() 34 ; CHECK-NEXT: br label [[FOR_INC_PEEL6:%.*]] 35 ; CHECK: if.then.peel5: 36 ; CHECK-NEXT: call void @f1() 37 ; CHECK-NEXT: br label [[FOR_INC_PEEL6]] 38 ; CHECK: for.inc.peel6: 39 ; CHECK-NEXT: [[INC_PEEL7:%.*]] = add nsw i32 [[INC_PEEL]], 1 40 ; CHECK-NEXT: [[CMP_PEEL8:%.*]] = icmp slt i32 [[INC_PEEL7]], [[K]] 41 ; CHECK-NEXT: br i1 [[CMP_PEEL8]], label [[FOR_BODY_PEEL_NEXT1:%.*]], label [[FOR_END]] 42 ; CHECK: for.body.peel.next1: 43 ; CHECK-NEXT: br label [[FOR_BODY_PEEL_NEXT9:%.*]] 44 ; CHECK: for.body.peel.next9: 45 ; CHECK-NEXT: br label [[FOR_BODY_LR_PH_PEEL_NEWPH:%.*]] 46 ; CHECK: for.body.lr.ph.peel.newph: 47 ; CHECK-NEXT: br label [[FOR_BODY:%.*]] 48 ; CHECK: for.body: 49 ; CHECK-NEXT: [[I_05:%.*]] = phi i32 [ [[INC_PEEL7]], [[FOR_BODY_LR_PH_PEEL_NEWPH]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ] 50 ; CHECK-NEXT: br i1 false, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 51 ; CHECK: if.then: 52 ; CHECK-NEXT: call void @f1() 53 ; CHECK-NEXT: br label [[FOR_INC]] 54 ; CHECK: if.else: 55 ; CHECK-NEXT: call void @f2() 56 ; CHECK-NEXT: br label [[FOR_INC]] 57 ; CHECK: for.inc: 58 ; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_05]], 1 59 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[INC]], [[K]] 60 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]], !llvm.loop !0 61 ; CHECK: for.end.loopexit: 62 ; CHECK-NEXT: br label [[FOR_END]] 63 ; CHECK: for.end: 64 ; CHECK-NEXT: ret void 65 ; 66 for.body.lr.ph: 67 br label %for.body 68 69 for.body: 70 %i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ] 71 %cmp1 = icmp ult i32 %i.05, 2 72 br i1 %cmp1, label %if.then, label %if.else 73 74 if.then: 75 call void @f1() 76 br label %for.inc 77 78 if.else: 79 call void @f2() 80 br label %for.inc 81 82 for.inc: 83 %inc = add nsw i32 %i.05, 1 84 %cmp = icmp slt i32 %inc, %k 85 br i1 %cmp, label %for.body, label %for.end 86 87 for.end: 88 ret void 89 } 90 91 ; Check we peel off the maximum number of iterations that make conditions true. 92 define void @test2(i32 %k) { 93 ; CHECK-LABEL: @test2( 94 ; CHECK-NEXT: for.body.lr.ph: 95 ; CHECK-NEXT: br label [[FOR_BODY_PEEL_BEGIN:%.*]] 96 ; CHECK: for.body.peel.begin: 97 ; CHECK-NEXT: br label [[FOR_BODY_PEEL:%.*]] 98 ; CHECK: for.body.peel: 99 ; CHECK-NEXT: [[CMP1_PEEL:%.*]] = icmp ult i32 0, 2 100 ; CHECK-NEXT: br i1 [[CMP1_PEEL]], label [[IF_THEN_PEEL:%.*]], label [[IF_ELSE_PEEL:%.*]] 101 ; CHECK: if.else.peel: 102 ; CHECK-NEXT: call void @f2() 103 ; CHECK-NEXT: br label [[IF2_PEEL:%.*]] 104 ; CHECK: if.then.peel: 105 ; CHECK-NEXT: call void @f1() 106 ; CHECK-NEXT: br label [[IF2_PEEL]] 107 ; CHECK: if2.peel: 108 ; CHECK-NEXT: [[CMP2_PEEL:%.*]] = icmp ult i32 0, 4 109 ; CHECK-NEXT: br i1 [[CMP2_PEEL]], label [[IF_THEN2_PEEL:%.*]], label [[FOR_INC_PEEL:%.*]] 110 ; CHECK: if.then2.peel: 111 ; CHECK-NEXT: call void @f1() 112 ; CHECK-NEXT: br label [[FOR_INC_PEEL]] 113 ; CHECK: for.inc.peel: 114 ; CHECK-NEXT: [[INC_PEEL:%.*]] = add nsw i32 0, 1 115 ; CHECK-NEXT: [[CMP_PEEL:%.*]] = icmp slt i32 [[INC_PEEL]], [[K:%.*]] 116 ; CHECK-NEXT: br i1 [[CMP_PEEL]], label [[FOR_BODY_PEEL_NEXT:%.*]], label [[FOR_END:%.*]] 117 ; CHECK: for.body.peel.next: 118 ; CHECK-NEXT: br label [[FOR_BODY_PEEL2:%.*]] 119 ; CHECK: for.body.peel2: 120 ; CHECK-NEXT: [[CMP1_PEEL3:%.*]] = icmp ult i32 [[INC_PEEL]], 2 121 ; CHECK-NEXT: br i1 [[CMP1_PEEL3]], label [[IF_THEN_PEEL5:%.*]], label [[IF_ELSE_PEEL4:%.*]] 122 ; CHECK: if.else.peel4: 123 ; CHECK-NEXT: call void @f2() 124 ; CHECK-NEXT: br label [[IF2_PEEL6:%.*]] 125 ; CHECK: if.then.peel5: 126 ; CHECK-NEXT: call void @f1() 127 ; CHECK-NEXT: br label [[IF2_PEEL6]] 128 ; CHECK: if2.peel6: 129 ; CHECK-NEXT: [[CMP2_PEEL7:%.*]] = icmp ult i32 [[INC_PEEL]], 4 130 ; CHECK-NEXT: br i1 [[CMP2_PEEL7]], label [[IF_THEN2_PEEL8:%.*]], label [[FOR_INC_PEEL9:%.*]] 131 ; CHECK: if.then2.peel8: 132 ; CHECK-NEXT: call void @f1() 133 ; CHECK-NEXT: br label [[FOR_INC_PEEL9]] 134 ; CHECK: for.inc.peel9: 135 ; CHECK-NEXT: [[INC_PEEL10:%.*]] = add nsw i32 [[INC_PEEL]], 1 136 ; CHECK-NEXT: [[CMP_PEEL11:%.*]] = icmp slt i32 [[INC_PEEL10]], [[K]] 137 ; CHECK-NEXT: br i1 [[CMP_PEEL11]], label [[FOR_BODY_PEEL_NEXT1:%.*]], label [[FOR_END]] 138 ; CHECK: for.body.peel.next1: 139 ; CHECK-NEXT: br label [[FOR_BODY_PEEL13:%.*]] 140 ; CHECK: for.body.peel13: 141 ; CHECK-NEXT: [[CMP1_PEEL14:%.*]] = icmp ult i32 [[INC_PEEL10]], 2 142 ; CHECK-NEXT: br i1 [[CMP1_PEEL14]], label [[IF_THEN_PEEL16:%.*]], label [[IF_ELSE_PEEL15:%.*]] 143 ; CHECK: if.else.peel15: 144 ; CHECK-NEXT: call void @f2() 145 ; CHECK-NEXT: br label [[IF2_PEEL17:%.*]] 146 ; CHECK: if.then.peel16: 147 ; CHECK-NEXT: call void @f1() 148 ; CHECK-NEXT: br label [[IF2_PEEL17]] 149 ; CHECK: if2.peel17: 150 ; CHECK-NEXT: [[CMP2_PEEL18:%.*]] = icmp ult i32 [[INC_PEEL10]], 4 151 ; CHECK-NEXT: br i1 [[CMP2_PEEL18]], label [[IF_THEN2_PEEL19:%.*]], label [[FOR_INC_PEEL20:%.*]] 152 ; CHECK: if.then2.peel19: 153 ; CHECK-NEXT: call void @f1() 154 ; CHECK-NEXT: br label [[FOR_INC_PEEL20]] 155 ; CHECK: for.inc.peel20: 156 ; CHECK-NEXT: [[INC_PEEL21:%.*]] = add nsw i32 [[INC_PEEL10]], 1 157 ; CHECK-NEXT: [[CMP_PEEL22:%.*]] = icmp slt i32 [[INC_PEEL21]], [[K]] 158 ; CHECK-NEXT: br i1 [[CMP_PEEL22]], label [[FOR_BODY_PEEL_NEXT12:%.*]], label [[FOR_END]] 159 ; CHECK: for.body.peel.next12: 160 ; CHECK-NEXT: br label [[FOR_BODY_PEEL24:%.*]] 161 ; CHECK: for.body.peel24: 162 ; CHECK-NEXT: [[CMP1_PEEL25:%.*]] = icmp ult i32 [[INC_PEEL21]], 2 163 ; CHECK-NEXT: br i1 [[CMP1_PEEL25]], label [[IF_THEN_PEEL27:%.*]], label [[IF_ELSE_PEEL26:%.*]] 164 ; CHECK: if.else.peel26: 165 ; CHECK-NEXT: call void @f2() 166 ; CHECK-NEXT: br label [[IF2_PEEL28:%.*]] 167 ; CHECK: if.then.peel27: 168 ; CHECK-NEXT: call void @f1() 169 ; CHECK-NEXT: br label [[IF2_PEEL28]] 170 ; CHECK: if2.peel28: 171 ; CHECK-NEXT: [[CMP2_PEEL29:%.*]] = icmp ult i32 [[INC_PEEL21]], 4 172 ; CHECK-NEXT: br i1 [[CMP2_PEEL29]], label [[IF_THEN2_PEEL30:%.*]], label [[FOR_INC_PEEL31:%.*]] 173 ; CHECK: if.then2.peel30: 174 ; CHECK-NEXT: call void @f1() 175 ; CHECK-NEXT: br label [[FOR_INC_PEEL31]] 176 ; CHECK: for.inc.peel31: 177 ; CHECK-NEXT: [[INC_PEEL32:%.*]] = add nsw i32 [[INC_PEEL21]], 1 178 ; CHECK-NEXT: [[CMP_PEEL33:%.*]] = icmp slt i32 [[INC_PEEL32]], [[K]] 179 ; CHECK-NEXT: br i1 [[CMP_PEEL33]], label [[FOR_BODY_PEEL_NEXT23:%.*]], label [[FOR_END]] 180 ; CHECK: for.body.peel.next23: 181 ; CHECK-NEXT: br label [[FOR_BODY_PEEL_NEXT34:%.*]] 182 ; CHECK: for.body.peel.next34: 183 ; CHECK-NEXT: br label [[FOR_BODY_LR_PH_PEEL_NEWPH:%.*]] 184 ; CHECK: for.body.lr.ph.peel.newph: 185 ; CHECK-NEXT: br label [[FOR_BODY:%.*]] 186 ; CHECK: for.body: 187 ; CHECK-NEXT: [[I_05:%.*]] = phi i32 [ [[INC_PEEL32]], [[FOR_BODY_LR_PH_PEEL_NEWPH]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ] 188 ; CHECK-NEXT: br i1 false, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 189 ; CHECK: if.then: 190 ; CHECK-NEXT: call void @f1() 191 ; CHECK-NEXT: br label [[IF2:%.*]] 192 ; CHECK: if.else: 193 ; CHECK-NEXT: call void @f2() 194 ; CHECK-NEXT: br label [[IF2]] 195 ; CHECK: if2: 196 ; CHECK-NEXT: br i1 false, label [[IF_THEN2:%.*]], label [[FOR_INC]] 197 ; CHECK: if.then2: 198 ; CHECK-NEXT: call void @f1() 199 ; CHECK-NEXT: br label [[FOR_INC]] 200 ; CHECK: for.inc: 201 ; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_05]], 1 202 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[INC]], [[K]] 203 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]], !llvm.loop !2 204 ; CHECK: for.end.loopexit: 205 ; CHECK-NEXT: br label [[FOR_END]] 206 ; CHECK: for.end: 207 ; CHECK-NEXT: ret void 208 ; 209 for.body.lr.ph: 210 br label %for.body 211 212 for.body: 213 %i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ] 214 %cmp1 = icmp ult i32 %i.05, 2 215 br i1 %cmp1, label %if.then, label %if.else 216 217 if.then: 218 call void @f1() 219 br label %if2 220 221 if.else: 222 call void @f2() 223 br label %if2 224 225 if2: 226 %cmp2 = icmp ult i32 %i.05, 4 227 br i1 %cmp2, label %if.then2, label %for.inc 228 229 if.then2: 230 call void @f1() 231 br label %for.inc 232 233 for.inc: 234 %inc = add nsw i32 %i.05, 1 235 %cmp = icmp slt i32 %inc, %k 236 br i1 %cmp, label %for.body, label %for.end 237 238 for.end: 239 ret void 240 } 241 242 ; Check that we can peel off iterations that make a condition false. 243 define void @test3(i32 %k) { 244 ; CHECK-LABEL: @test3( 245 ; CHECK-NEXT: for.body.lr.ph: 246 ; CHECK-NEXT: br label [[FOR_BODY_PEEL_BEGIN:%.*]] 247 ; CHECK: for.body.peel.begin: 248 ; CHECK-NEXT: br label [[FOR_BODY_PEEL:%.*]] 249 ; CHECK: for.body.peel: 250 ; CHECK-NEXT: [[CMP1_PEEL:%.*]] = icmp ugt i32 0, 2 251 ; CHECK-NEXT: br i1 [[CMP1_PEEL]], label [[IF_THEN_PEEL:%.*]], label [[IF_ELSE_PEEL:%.*]] 252 ; CHECK: if.else.peel: 253 ; CHECK-NEXT: call void @f2() 254 ; CHECK-NEXT: br label [[FOR_INC_PEEL:%.*]] 255 ; CHECK: if.then.peel: 256 ; CHECK-NEXT: call void @f1() 257 ; CHECK-NEXT: br label [[FOR_INC_PEEL]] 258 ; CHECK: for.inc.peel: 259 ; CHECK-NEXT: [[INC_PEEL:%.*]] = add nsw i32 0, 1 260 ; CHECK-NEXT: [[CMP_PEEL:%.*]] = icmp slt i32 [[INC_PEEL]], [[K:%.*]] 261 ; CHECK-NEXT: br i1 [[CMP_PEEL]], label [[FOR_BODY_PEEL_NEXT:%.*]], label [[FOR_END:%.*]] 262 ; CHECK: for.body.peel.next: 263 ; CHECK-NEXT: br label [[FOR_BODY_PEEL2:%.*]] 264 ; CHECK: for.body.peel2: 265 ; CHECK-NEXT: [[CMP1_PEEL3:%.*]] = icmp ugt i32 [[INC_PEEL]], 2 266 ; CHECK-NEXT: br i1 [[CMP1_PEEL3]], label [[IF_THEN_PEEL5:%.*]], label [[IF_ELSE_PEEL4:%.*]] 267 ; CHECK: if.else.peel4: 268 ; CHECK-NEXT: call void @f2() 269 ; CHECK-NEXT: br label [[FOR_INC_PEEL6:%.*]] 270 ; CHECK: if.then.peel5: 271 ; CHECK-NEXT: call void @f1() 272 ; CHECK-NEXT: br label [[FOR_INC_PEEL6]] 273 ; CHECK: for.inc.peel6: 274 ; CHECK-NEXT: [[INC_PEEL7:%.*]] = add nsw i32 [[INC_PEEL]], 1 275 ; CHECK-NEXT: [[CMP_PEEL8:%.*]] = icmp slt i32 [[INC_PEEL7]], [[K]] 276 ; CHECK-NEXT: br i1 [[CMP_PEEL8]], label [[FOR_BODY_PEEL_NEXT1:%.*]], label [[FOR_END]] 277 ; CHECK: for.body.peel.next1: 278 ; CHECK-NEXT: br label [[FOR_BODY_PEEL10:%.*]] 279 ; CHECK: for.body.peel10: 280 ; CHECK-NEXT: [[CMP1_PEEL11:%.*]] = icmp ugt i32 [[INC_PEEL7]], 2 281 ; CHECK-NEXT: br i1 [[CMP1_PEEL11]], label [[IF_THEN_PEEL13:%.*]], label [[IF_ELSE_PEEL12:%.*]] 282 ; CHECK: if.else.peel12: 283 ; CHECK-NEXT: call void @f2() 284 ; CHECK-NEXT: br label [[FOR_INC_PEEL14:%.*]] 285 ; CHECK: if.then.peel13: 286 ; CHECK-NEXT: call void @f1() 287 ; CHECK-NEXT: br label [[FOR_INC_PEEL14]] 288 ; CHECK: for.inc.peel14: 289 ; CHECK-NEXT: [[INC_PEEL15:%.*]] = add nsw i32 [[INC_PEEL7]], 1 290 ; CHECK-NEXT: [[CMP_PEEL16:%.*]] = icmp slt i32 [[INC_PEEL15]], [[K]] 291 ; CHECK-NEXT: br i1 [[CMP_PEEL16]], label [[FOR_BODY_PEEL_NEXT9:%.*]], label [[FOR_END]] 292 ; CHECK: for.body.peel.next9: 293 ; CHECK-NEXT: br label [[FOR_BODY_PEEL_NEXT17:%.*]] 294 ; CHECK: for.body.peel.next17: 295 ; CHECK-NEXT: br label [[FOR_BODY_LR_PH_PEEL_NEWPH:%.*]] 296 ; CHECK: for.body.lr.ph.peel.newph: 297 ; CHECK-NEXT: br label [[FOR_BODY:%.*]] 298 ; CHECK: for.body: 299 ; CHECK-NEXT: [[I_05:%.*]] = phi i32 [ [[INC_PEEL15]], [[FOR_BODY_LR_PH_PEEL_NEWPH]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ] 300 ; CHECK-NEXT: br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 301 ; CHECK: if.then: 302 ; CHECK-NEXT: call void @f1() 303 ; CHECK-NEXT: br label [[FOR_INC]] 304 ; CHECK: if.else: 305 ; CHECK-NEXT: call void @f2() 306 ; CHECK-NEXT: br label [[FOR_INC]] 307 ; CHECK: for.inc: 308 ; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_05]], 1 309 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[INC]], [[K]] 310 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]], !llvm.loop !3 311 ; CHECK: for.end.loopexit: 312 ; CHECK-NEXT: br label [[FOR_END]] 313 ; CHECK: for.end: 314 ; CHECK-NEXT: ret void 315 ; 316 for.body.lr.ph: 317 br label %for.body 318 319 for.body: 320 %i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ] 321 %cmp1 = icmp ugt i32 %i.05, 2 322 br i1 %cmp1, label %if.then, label %if.else 323 324 if.then: 325 call void @f1() 326 br label %for.inc 327 328 if.else: 329 call void @f2() 330 br label %for.inc 331 332 for.inc: 333 %inc = add nsw i32 %i.05, 1 334 %cmp = icmp slt i32 %inc, %k 335 br i1 %cmp, label %for.body, label %for.end 336 337 for.end: 338 ret void 339 } 340 341 ; Test that we only peel off iterations if it simplifies a condition in the 342 ; loop body after peeling at most MaxPeelCount iterations. 343 define void @test4(i32 %k) { 344 ; CHECK-LABEL: @test4( 345 ; CHECK-NEXT: for.body.lr.ph: 346 ; CHECK-NEXT: br label [[FOR_BODY:%.*]] 347 ; CHECK: for.body: 348 ; CHECK-NEXT: [[I_05:%.*]] = phi i32 [ 0, [[FOR_BODY_LR_PH:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ] 349 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i32 [[I_05]], 9999 350 ; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]] 351 ; CHECK: if.then: 352 ; CHECK-NEXT: call void @f1() 353 ; CHECK-NEXT: br label [[FOR_INC]] 354 ; CHECK: for.inc: 355 ; CHECK-NEXT: [[INC]] = add nsw i32 [[I_05]], 1 356 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[INC]], [[K:%.*]] 357 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 358 ; CHECK: for.end: 359 ; CHECK-NEXT: ret void 360 ; 361 for.body.lr.ph: 362 br label %for.body 363 364 for.body: 365 %i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ] 366 %cmp1 = icmp ugt i32 %i.05, 9999 367 br i1 %cmp1, label %if.then, label %for.inc 368 369 if.then: 370 call void @f1() 371 br label %for.inc 372 373 for.inc: 374 %inc = add nsw i32 %i.05, 1 375 %cmp = icmp slt i32 %inc, %k 376 br i1 %cmp, label %for.body, label %for.end 377 378 for.end: 379 ret void 380 } 381 382 ; In this case we cannot peel the inner loop, because the condition involves 383 ; the outer induction variable. 384 define void @test5(i32 %k) { 385 ; CHECK-LABEL: @test5( 386 ; CHECK-NEXT: for.body.lr.ph: 387 ; CHECK-NEXT: br label [[OUTER_HEADER:%.*]] 388 ; CHECK: outer.header: 389 ; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[FOR_BODY_LR_PH:%.*]] ], [ [[J_INC:%.*]], [[OUTER_INC:%.*]] ] 390 ; CHECK-NEXT: br label [[FOR_BODY:%.*]] 391 ; CHECK: for.body: 392 ; CHECK-NEXT: [[I_05:%.*]] = phi i32 [ 0, [[OUTER_HEADER]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ] 393 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[J]], 2 394 ; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 395 ; CHECK: if.then: 396 ; CHECK-NEXT: call void @f1() 397 ; CHECK-NEXT: br label [[FOR_INC]] 398 ; CHECK: if.else: 399 ; CHECK-NEXT: call void @f2() 400 ; CHECK-NEXT: br label [[FOR_INC]] 401 ; CHECK: for.inc: 402 ; CHECK-NEXT: [[INC]] = add nsw i32 [[I_05]], 1 403 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[INC]], [[K:%.*]] 404 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[OUTER_INC]] 405 ; CHECK: outer.inc: 406 ; CHECK-NEXT: [[J_INC]] = add nsw i32 [[J]], 1 407 ; CHECK-NEXT: [[OUTER_CMP:%.*]] = icmp slt i32 [[J_INC]], [[K]] 408 ; CHECK-NEXT: br i1 [[OUTER_CMP]], label [[OUTER_HEADER]], label [[FOR_END:%.*]] 409 ; CHECK: for.end: 410 ; CHECK-NEXT: ret void 411 ; 412 for.body.lr.ph: 413 br label %outer.header 414 415 outer.header: 416 %j = phi i32 [ 0, %for.body.lr.ph ], [ %j.inc, %outer.inc ] 417 br label %for.body 418 419 for.body: 420 %i.05 = phi i32 [ 0, %outer.header ], [ %inc, %for.inc ] 421 %cmp1 = icmp ult i32 %j, 2 422 br i1 %cmp1, label %if.then, label %if.else 423 424 if.then: 425 call void @f1() 426 br label %for.inc 427 428 if.else: 429 call void @f2() 430 br label %for.inc 431 432 for.inc: 433 %inc = add nsw i32 %i.05, 1 434 %cmp = icmp slt i32 %inc, %k 435 br i1 %cmp, label %for.body, label %outer.inc 436 437 outer.inc: 438 %j.inc = add nsw i32 %j, 1 439 %outer.cmp = icmp slt i32 %j.inc, %k 440 br i1 %outer.cmp, label %outer.header, label %for.end 441 442 443 for.end: 444 ret void 445 } 446 447 ; In this test, the condition involves 2 AddRecs. Without evaluating both 448 ; AddRecs, we cannot prove that the condition becomes known in the loop body 449 ; after peeling. 450 define void @test6(i32 %k) { 451 ; CHECK-LABEL: @test6( 452 ; CHECK-NEXT: entry: 453 ; CHECK-NEXT: br label [[FOR_BODY:%.*]] 454 ; CHECK: for.body: 455 ; CHECK-NEXT: [[I_05:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ] 456 ; CHECK-NEXT: [[J:%.*]] = phi i32 [ 4, [[ENTRY]] ], [ [[J_INC:%.*]], [[FOR_INC]] ] 457 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[I_05]], [[J]] 458 ; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 459 ; CHECK: if.then: 460 ; CHECK-NEXT: call void @f1() 461 ; CHECK-NEXT: br label [[FOR_INC]] 462 ; CHECK: if.else: 463 ; CHECK-NEXT: call void @f2() 464 ; CHECK-NEXT: br label [[FOR_INC]] 465 ; CHECK: for.inc: 466 ; CHECK-NEXT: [[INC]] = add nsw i32 [[I_05]], 2 467 ; CHECK-NEXT: [[J_INC]] = add nsw i32 [[J]], 1 468 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[INC]], [[K:%.*]] 469 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 470 ; CHECK: for.end: 471 ; CHECK-NEXT: ret void 472 ; 473 entry: 474 br label %for.body 475 476 for.body: 477 %i.05 = phi i32 [ 0, %entry ], [ %inc, %for.inc ] 478 %j = phi i32 [ 4, %entry ], [ %j.inc, %for.inc ] 479 %cmp1 = icmp ult i32 %i.05, %j 480 br i1 %cmp1, label %if.then, label %if.else 481 482 if.then: 483 call void @f1() 484 br label %for.inc 485 486 if.else: 487 call void @f2() 488 br label %for.inc 489 490 for.inc: 491 %inc = add nsw i32 %i.05, 2 492 %j.inc = add nsw i32 %j, 1 493 %cmp = icmp slt i32 %inc, %k 494 br i1 %cmp, label %for.body, label %for.end 495 496 for.end: 497 ret void 498 } 499 500 define void @test7(i32 %k) { 501 ; FIXME: Could simplify loop body by peeling one additional iteration after 502 ; i != 3 becomes false 503 ; CHECK-LABEL: @test7( 504 ; CHECK-NEXT: for.body.lr.ph: 505 ; CHECK-NEXT: br label [[FOR_BODY:%.*]] 506 ; CHECK: for.body: 507 ; CHECK-NEXT: [[I_05:%.*]] = phi i32 [ 0, [[FOR_BODY_LR_PH:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ] 508 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[I_05]], 3 509 ; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]] 510 ; CHECK: if.then: 511 ; CHECK-NEXT: call void @f1() 512 ; CHECK-NEXT: br label [[FOR_INC]] 513 ; CHECK: for.inc: 514 ; CHECK-NEXT: [[INC]] = add nsw i32 [[I_05]], 1 515 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[INC]], [[K:%.*]] 516 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 517 ; CHECK: for.end: 518 ; CHECK-NEXT: ret void 519 ; 520 for.body.lr.ph: 521 br label %for.body 522 523 for.body: 524 %i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ] 525 %cmp1 = icmp ne i32 %i.05, 3 526 br i1 %cmp1, label %if.then, label %for.inc 527 528 if.then: 529 call void @f1() 530 br label %for.inc 531 532 for.inc: 533 %inc = add nsw i32 %i.05, 1 534 %cmp = icmp slt i32 %inc, %k 535 br i1 %cmp, label %for.body, label %for.end 536 537 for.end: 538 ret void 539 } 540 541 define void @test8(i32 %k) { 542 ; FIXME: Could simplify loop body by peeling one additional iteration after 543 ; i == 3 becomes true. 544 ; CHECK-LABEL: @test8( 545 ; CHECK-NEXT: for.body.lr.ph: 546 ; CHECK-NEXT: br label [[FOR_BODY:%.*]] 547 ; CHECK: for.body: 548 ; CHECK-NEXT: [[I_05:%.*]] = phi i32 [ 0, [[FOR_BODY_LR_PH:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ] 549 ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[I_05]], 3 550 ; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]] 551 ; CHECK: if.then: 552 ; CHECK-NEXT: call void @f1() 553 ; CHECK-NEXT: br label [[FOR_INC]] 554 ; CHECK: for.inc: 555 ; CHECK-NEXT: [[INC]] = add nsw i32 [[I_05]], 1 556 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[INC]], [[K:%.*]] 557 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 558 ; CHECK: for.end: 559 ; CHECK-NEXT: ret void 560 ; 561 for.body.lr.ph: 562 br label %for.body 563 564 for.body: 565 %i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ] 566 %cmp1 = icmp eq i32 %i.05, 3 567 br i1 %cmp1, label %if.then, label %for.inc 568 569 if.then: 570 call void @f1() 571 br label %for.inc 572 573 for.inc: 574 %inc = add nsw i32 %i.05, 1 575 %cmp = icmp slt i32 %inc, %k 576 br i1 %cmp, label %for.body, label %for.end 577 578 for.end: 579 ret void 580 } 581 582 ; Comparison with non-monotonic predicate due to possible wrapping, loop 583 ; body cannot be simplified. 584 define void @test9(i32 %k) { 585 ; CHECK-LABEL: @test9( 586 ; CHECK-NEXT: for.body.lr.ph: 587 ; CHECK-NEXT: br label [[FOR_BODY:%.*]] 588 ; CHECK: for.body: 589 ; CHECK-NEXT: [[I_05:%.*]] = phi i32 [ 0, [[FOR_BODY_LR_PH:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ] 590 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[I_05]], 3 591 ; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]] 592 ; CHECK: if.then: 593 ; CHECK-NEXT: call void @f1() 594 ; CHECK-NEXT: br label [[FOR_INC]] 595 ; CHECK: for.inc: 596 ; CHECK-NEXT: [[INC]] = add i32 [[I_05]], 1 597 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[INC]], [[K:%.*]] 598 ; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 599 ; CHECK: for.end: 600 ; CHECK-NEXT: ret void 601 ; 602 for.body.lr.ph: 603 br label %for.body 604 605 for.body: 606 %i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ] 607 %cmp1 = icmp slt i32 %i.05, 3 608 br i1 %cmp1, label %if.then, label %for.inc 609 610 if.then: 611 call void @f1() 612 br label %for.inc 613 614 for.inc: 615 %inc = add i32 %i.05, 1 616 %cmp = icmp slt i32 %inc, %k 617 br i1 %cmp, label %for.body, label %for.end 618 619 for.end: 620 ret void 621 } 622