1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 2; RUN: opt -p constraint-elimination -S %s | FileCheck %s 3 4declare void @llvm.assume(i1) 5 6define i1 @multi_exiting_loop_eq_same_unique_exit_const_compare_known(ptr %s) { 7; CHECK-LABEL: define i1 @multi_exiting_loop_eq_same_unique_exit_const_compare_known( 8; CHECK-SAME: ptr [[S:%.*]]) { 9; CHECK-NEXT: [[ENTRY:.*]]: 10; CHECK-NEXT: br label %[[LOOP_HEADER:.*]] 11; CHECK: [[LOOP_HEADER]]: 12; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] 13; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], 1234 14; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP_LATCH]] 15; CHECK: [[LOOP_LATCH]]: 16; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]] 17; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 18; CHECK-NEXT: [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10 19; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 20; CHECK-NEXT: br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT]] 21; CHECK: [[EXIT]]: 22; CHECK-NEXT: ret i1 true 23; 24entry: 25 br label %loop.header 26 27loop.header: 28 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] 29 %exitcond.not = icmp eq i32 %iv, 1234 30 br i1 %exitcond.not, label %exit, label %loop.latch 31 32loop.latch: 33 %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv 34 %0 = load i8, ptr %arrayidx, align 1 35 %latch.c = icmp ult i8 %0, 10 36 %iv.next = add nuw nsw i32 %iv, 1 37 br i1 %latch.c, label %loop.header, label %exit 38 39exit: 40 %t = icmp ult i32 %iv, 1235 41 ret i1 %t 42} 43 44define i1 @multi_exiting_loop_eq_same_unique_exit_const_compare_not_known_due_to_start_value(ptr %s) { 45; CHECK-LABEL: define i1 @multi_exiting_loop_eq_same_unique_exit_const_compare_not_known_due_to_start_value( 46; CHECK-SAME: ptr [[S:%.*]]) { 47; CHECK-NEXT: [[ENTRY:.*]]: 48; CHECK-NEXT: br label %[[LOOP_HEADER:.*]] 49; CHECK: [[LOOP_HEADER]]: 50; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 1235, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] 51; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], 1234 52; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP_LATCH]] 53; CHECK: [[LOOP_LATCH]]: 54; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]] 55; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 56; CHECK-NEXT: [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10 57; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 58; CHECK-NEXT: br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT]] 59; CHECK: [[EXIT]]: 60; CHECK-NEXT: [[T:%.*]] = icmp ult i32 [[IV]], 1235 61; CHECK-NEXT: ret i1 [[T]] 62; 63entry: 64 br label %loop.header 65 66loop.header: 67 %iv = phi i32 [ 1235, %entry ], [ %iv.next, %loop.latch ] 68 %exitcond.not = icmp eq i32 %iv, 1234 69 br i1 %exitcond.not, label %exit, label %loop.latch 70 71loop.latch: 72 %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv 73 %0 = load i8, ptr %arrayidx, align 1 74 %latch.c = icmp ult i8 %0, 10 75 %iv.next = add i32 %iv, 1 76 br i1 %latch.c, label %loop.header, label %exit 77 78exit: 79 %t = icmp ult i32 %iv, 1235 80 ret i1 %t 81} 82 83define i1 @multi_exiting_loop_eq_same_unique_exit_const_compare_known_due_to_precond_on_start_value(ptr %s, i32 %start) { 84; CHECK-LABEL: define i1 @multi_exiting_loop_eq_same_unique_exit_const_compare_known_due_to_precond_on_start_value( 85; CHECK-SAME: ptr [[S:%.*]], i32 [[START:%.*]]) { 86; CHECK-NEXT: [[ENTRY:.*]]: 87; CHECK-NEXT: [[PRE_C:%.*]] = icmp ule i32 [[START]], 1234 88; CHECK-NEXT: call void @llvm.assume(i1 [[PRE_C]]) 89; CHECK-NEXT: br label %[[LOOP_HEADER:.*]] 90; CHECK: [[LOOP_HEADER]]: 91; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START]], %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] 92; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], 1234 93; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP_LATCH]] 94; CHECK: [[LOOP_LATCH]]: 95; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]] 96; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 97; CHECK-NEXT: [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10 98; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 99; CHECK-NEXT: br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT]] 100; CHECK: [[EXIT]]: 101; CHECK-NEXT: ret i1 true 102; 103entry: 104 %pre.c = icmp ule i32 %start, 1234 105 call void @llvm.assume(i1 %pre.c) 106 br label %loop.header 107 108loop.header: 109 %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop.latch ] 110 %exitcond.not = icmp eq i32 %iv, 1234 111 br i1 %exitcond.not, label %exit, label %loop.latch 112 113loop.latch: 114 %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv 115 %0 = load i8, ptr %arrayidx, align 1 116 %latch.c = icmp ult i8 %0, 10 117 %iv.next = add i32 %iv, 1 118 br i1 %latch.c, label %loop.header, label %exit 119 120exit: 121 %t = icmp ult i32 %iv, 1235 122 ret i1 %t 123} 124 125define i1 @multi_exiting_loop_eq_same_unique_exit_const_compare_not_known_due_to_precond_on_start_value(ptr %s, i32 %start) { 126; CHECK-LABEL: define i1 @multi_exiting_loop_eq_same_unique_exit_const_compare_not_known_due_to_precond_on_start_value( 127; CHECK-SAME: ptr [[S:%.*]], i32 [[START:%.*]]) { 128; CHECK-NEXT: [[ENTRY:.*]]: 129; CHECK-NEXT: [[PRE_C:%.*]] = icmp ule i32 [[START]], 1236 130; CHECK-NEXT: call void @llvm.assume(i1 [[PRE_C]]) 131; CHECK-NEXT: br label %[[LOOP_HEADER:.*]] 132; CHECK: [[LOOP_HEADER]]: 133; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START]], %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] 134; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], 1234 135; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP_LATCH]] 136; CHECK: [[LOOP_LATCH]]: 137; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]] 138; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 139; CHECK-NEXT: [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10 140; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 141; CHECK-NEXT: br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT]] 142; CHECK: [[EXIT]]: 143; CHECK-NEXT: [[T:%.*]] = icmp ult i32 [[IV]], 1236 144; CHECK-NEXT: ret i1 [[T]] 145; 146entry: 147 %pre.c = icmp ule i32 %start, 1236 148 call void @llvm.assume(i1 %pre.c) 149 br label %loop.header 150 151loop.header: 152 %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop.latch ] 153 %exitcond.not = icmp eq i32 %iv, 1234 154 br i1 %exitcond.not, label %exit, label %loop.latch 155 156loop.latch: 157 %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv 158 %0 = load i8, ptr %arrayidx, align 1 159 %latch.c = icmp ult i8 %0, 10 160 %iv.next = add i32 %iv, 1 161 br i1 %latch.c, label %loop.header, label %exit 162 163exit: 164 %t = icmp ult i32 %iv, 1236 165 ret i1 %t 166} 167 168define i1 @multi_exiting_loop_eq_same_unique_exit_const_compare_not_known_due_to_missing_precond(ptr %s, i32 %start) { 169; CHECK-LABEL: define i1 @multi_exiting_loop_eq_same_unique_exit_const_compare_not_known_due_to_missing_precond( 170; CHECK-SAME: ptr [[S:%.*]], i32 [[START:%.*]]) { 171; CHECK-NEXT: [[ENTRY:.*]]: 172; CHECK-NEXT: br label %[[LOOP_HEADER:.*]] 173; CHECK: [[LOOP_HEADER]]: 174; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START]], %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] 175; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], 1234 176; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP_LATCH]] 177; CHECK: [[LOOP_LATCH]]: 178; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]] 179; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 180; CHECK-NEXT: [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10 181; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 182; CHECK-NEXT: br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT]] 183; CHECK: [[EXIT]]: 184; CHECK-NEXT: [[T:%.*]] = icmp ult i32 [[IV]], 1236 185; CHECK-NEXT: ret i1 [[T]] 186; 187entry: 188 br label %loop.header 189 190loop.header: 191 %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop.latch ] 192 %exitcond.not = icmp eq i32 %iv, 1234 193 br i1 %exitcond.not, label %exit, label %loop.latch 194 195loop.latch: 196 %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv 197 %0 = load i8, ptr %arrayidx, align 1 198 %latch.c = icmp ult i8 %0, 10 199 %iv.next = add i32 %iv, 1 200 br i1 %latch.c, label %loop.header, label %exit 201 202exit: 203 %t = icmp ult i32 %iv, 1236 204 ret i1 %t 205} 206 207define i1 @multi_exiting_loop_eq_same_exit_with_out_loop_preds_const_compare_not_known(ptr %s, i1 %pre.c, i32 %x) { 208; CHECK-LABEL: define i1 @multi_exiting_loop_eq_same_exit_with_out_loop_preds_const_compare_not_known( 209; CHECK-SAME: ptr [[S:%.*]], i1 [[PRE_C:%.*]], i32 [[X:%.*]]) { 210; CHECK-NEXT: [[ENTRY:.*]]: 211; CHECK-NEXT: br i1 [[PRE_C]], label %[[LOOP_HEADER:.*]], label %[[EXIT:.*]] 212; CHECK: [[LOOP_HEADER]]: 213; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] 214; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], 1234 215; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT]], label %[[LOOP_LATCH]] 216; CHECK: [[LOOP_LATCH]]: 217; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]] 218; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 219; CHECK-NEXT: [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10 220; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 221; CHECK-NEXT: br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT]] 222; CHECK: [[EXIT]]: 223; CHECK-NEXT: [[P:%.*]] = phi i32 [ [[X]], %[[ENTRY]] ], [ [[IV]], %[[LOOP_HEADER]] ], [ [[IV]], %[[LOOP_LATCH]] ] 224; CHECK-NEXT: [[U:%.*]] = icmp ult i32 [[P]], 1235 225; CHECK-NEXT: ret i1 [[U]] 226; 227entry: 228 br i1 %pre.c, label %loop.header, label %exit 229 230loop.header: 231 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] 232 %exitcond.not = icmp eq i32 %iv, 1234 233 br i1 %exitcond.not, label %exit, label %loop.latch 234 235loop.latch: 236 %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv 237 %0 = load i8, ptr %arrayidx, align 1 238 %latch.c = icmp ult i8 %0, 10 239 %iv.next = add nuw nsw i32 %iv, 1 240 br i1 %latch.c, label %loop.header, label %exit 241 242exit: 243 %p = phi i32 [ %x, %entry ], [ %iv, %loop.header ], [ %iv, %loop.latch ] 244 %u = icmp ult i32 %p, 1235 245 ret i1 %u 246} 247 248define i1 @multi_exiting_loop_eq_same_unique_exit_successors_swapped(ptr %s) { 249; CHECK-LABEL: define i1 @multi_exiting_loop_eq_same_unique_exit_successors_swapped( 250; CHECK-SAME: ptr [[S:%.*]]) { 251; CHECK-NEXT: [[ENTRY:.*]]: 252; CHECK-NEXT: br label %[[LOOP_HEADER:.*]] 253; CHECK: [[LOOP_HEADER]]: 254; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] 255; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], 1234 256; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[LOOP_LATCH]], label %[[EXIT:.*]] 257; CHECK: [[LOOP_LATCH]]: 258; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]] 259; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 260; CHECK-NEXT: [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10 261; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 262; CHECK-NEXT: br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT]] 263; CHECK: [[EXIT]]: 264; CHECK-NEXT: [[U:%.*]] = icmp ult i32 [[IV]], 1235 265; CHECK-NEXT: ret i1 [[U]] 266; 267entry: 268 br label %loop.header 269 270loop.header: 271 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] 272 %exitcond.not = icmp eq i32 %iv, 1234 273 br i1 %exitcond.not, label %loop.latch, label %exit 274 275loop.latch: 276 %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv 277 %0 = load i8, ptr %arrayidx, align 1 278 %latch.c = icmp ult i8 %0, 10 279 %iv.next = add nuw nsw i32 %iv, 1 280 br i1 %latch.c, label %loop.header, label %exit 281 282exit: 283 %u = icmp ult i32 %iv, 1235 284 ret i1 %u 285} 286 287define i1 @multi_exiting_loop_eq_same_unique_exit_const_compare_not_known(ptr %s) { 288; CHECK-LABEL: define i1 @multi_exiting_loop_eq_same_unique_exit_const_compare_not_known( 289; CHECK-SAME: ptr [[S:%.*]]) { 290; CHECK-NEXT: [[ENTRY:.*]]: 291; CHECK-NEXT: br label %[[LOOP_HEADER:.*]] 292; CHECK: [[LOOP_HEADER]]: 293; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] 294; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], 1234 295; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP_LATCH]] 296; CHECK: [[LOOP_LATCH]]: 297; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]] 298; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 299; CHECK-NEXT: [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10 300; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 301; CHECK-NEXT: br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT]] 302; CHECK: [[EXIT]]: 303; CHECK-NEXT: [[U:%.*]] = icmp ult i32 [[IV]], 1234 304; CHECK-NEXT: ret i1 [[U]] 305; 306entry: 307 br label %loop.header 308 309loop.header: 310 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] 311 %exitcond.not = icmp eq i32 %iv, 1234 312 br i1 %exitcond.not, label %exit, label %loop.latch 313 314loop.latch: 315 %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv 316 %0 = load i8, ptr %arrayidx, align 1 317 %latch.c = icmp ult i8 %0, 10 318 %iv.next = add nuw nsw i32 %iv, 1 319 br i1 %latch.c, label %loop.header, label %exit 320 321exit: 322 %u = icmp ult i32 %iv, 1234 323 ret i1 %u 324} 325 326define i1 @multi_exiting_loop_eq_same_unique_exit_var_compare_known(ptr %s, i32 %N) { 327; CHECK-LABEL: define i1 @multi_exiting_loop_eq_same_unique_exit_var_compare_known( 328; CHECK-SAME: ptr [[S:%.*]], i32 [[N:%.*]]) { 329; CHECK-NEXT: [[ENTRY:.*]]: 330; CHECK-NEXT: br label %[[LOOP_HEADER:.*]] 331; CHECK: [[LOOP_HEADER]]: 332; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] 333; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], [[N]] 334; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP_LATCH]] 335; CHECK: [[LOOP_LATCH]]: 336; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]] 337; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 338; CHECK-NEXT: [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10 339; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 340; CHECK-NEXT: br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT]] 341; CHECK: [[EXIT]]: 342; CHECK-NEXT: ret i1 true 343; 344entry: 345 br label %loop.header 346 347loop.header: 348 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] 349 %exitcond.not = icmp eq i32 %iv, %N 350 br i1 %exitcond.not, label %exit, label %loop.latch 351 352loop.latch: 353 %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv 354 %0 = load i8, ptr %arrayidx, align 1 355 %latch.c = icmp ult i8 %0, 10 356 %iv.next = add nuw nsw i32 %iv, 1 357 br i1 %latch.c, label %loop.header, label %exit 358 359exit: 360 %t = icmp ule i32 %iv, %N 361 ret i1 %t 362} 363 364define i1 @multi_exiting_loop_eq_same_unique_exit_var_compare_not_known_due_to_start(ptr %s, i32 %N) { 365; CHECK-LABEL: define i1 @multi_exiting_loop_eq_same_unique_exit_var_compare_not_known_due_to_start( 366; CHECK-SAME: ptr [[S:%.*]], i32 [[N:%.*]]) { 367; CHECK-NEXT: [[ENTRY:.*]]: 368; CHECK-NEXT: br label %[[LOOP_HEADER:.*]] 369; CHECK: [[LOOP_HEADER]]: 370; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 1, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] 371; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], [[N]] 372; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP_LATCH]] 373; CHECK: [[LOOP_LATCH]]: 374; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]] 375; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 376; CHECK-NEXT: [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10 377; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 378; CHECK-NEXT: br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT]] 379; CHECK: [[EXIT]]: 380; CHECK-NEXT: [[C:%.*]] = icmp ule i32 [[IV]], [[N]] 381; CHECK-NEXT: ret i1 [[C]] 382; 383entry: 384 br label %loop.header 385 386loop.header: 387 %iv = phi i32 [ 1, %entry ], [ %iv.next, %loop.latch ] 388 %exitcond.not = icmp eq i32 %iv, %N 389 br i1 %exitcond.not, label %exit, label %loop.latch 390 391loop.latch: 392 %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv 393 %0 = load i8, ptr %arrayidx, align 1 394 %latch.c = icmp ult i8 %0, 10 395 %iv.next = add nuw nsw i32 %iv, 1 396 br i1 %latch.c, label %loop.header, label %exit 397 398exit: 399 %c = icmp ule i32 %iv, %N 400 ret i1 %c 401} 402 403define i1 @multi_exiting_loop_ne_same_unique_exit_const_compare_known(ptr %s) { 404; CHECK-LABEL: define i1 @multi_exiting_loop_ne_same_unique_exit_const_compare_known( 405; CHECK-SAME: ptr [[S:%.*]]) { 406; CHECK-NEXT: [[ENTRY:.*]]: 407; CHECK-NEXT: br label %[[LOOP_HEADER:.*]] 408; CHECK: [[LOOP_HEADER]]: 409; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] 410; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp ne i32 [[IV]], 1234 411; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[LOOP_LATCH]], label %[[EXIT:.*]] 412; CHECK: [[LOOP_LATCH]]: 413; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]] 414; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 415; CHECK-NEXT: [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10 416; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 417; CHECK-NEXT: br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT]] 418; CHECK: [[EXIT]]: 419; CHECK-NEXT: ret i1 true 420; 421entry: 422 br label %loop.header 423 424loop.header: 425 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] 426 %exitcond.not = icmp ne i32 %iv, 1234 427 br i1 %exitcond.not, label %loop.latch, label %exit 428 429loop.latch: 430 %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv 431 %0 = load i8, ptr %arrayidx, align 1 432 %latch.c = icmp ult i8 %0, 10 433 %iv.next = add nuw nsw i32 %iv, 1 434 br i1 %latch.c, label %loop.header, label %exit 435 436exit: 437 %t = icmp ult i32 %iv, 1235 438 ret i1 %t 439} 440 441define i1 @multi_exiting_loop_ne_same_unique_exit_successors_swapped(ptr %s) { 442; CHECK-LABEL: define i1 @multi_exiting_loop_ne_same_unique_exit_successors_swapped( 443; CHECK-SAME: ptr [[S:%.*]]) { 444; CHECK-NEXT: [[ENTRY:.*]]: 445; CHECK-NEXT: br label %[[LOOP_HEADER:.*]] 446; CHECK: [[LOOP_HEADER]]: 447; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] 448; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp ne i32 [[IV]], 1234 449; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP_LATCH]] 450; CHECK: [[LOOP_LATCH]]: 451; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]] 452; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 453; CHECK-NEXT: [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10 454; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 455; CHECK-NEXT: br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT]] 456; CHECK: [[EXIT]]: 457; CHECK-NEXT: [[U:%.*]] = icmp ult i32 [[IV]], 1235 458; CHECK-NEXT: ret i1 [[U]] 459; 460entry: 461 br label %loop.header 462 463loop.header: 464 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] 465 %exitcond.not = icmp ne i32 %iv, 1234 466 br i1 %exitcond.not, label %exit, label %loop.latch 467 468loop.latch: 469 %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv 470 %0 = load i8, ptr %arrayidx, align 1 471 %latch.c = icmp ult i8 %0, 10 472 %iv.next = add nuw nsw i32 %iv, 1 473 br i1 %latch.c, label %loop.header, label %exit 474 475exit: 476 %u = icmp ult i32 %iv, 1235 477 ret i1 %u 478} 479 480define i1 @multi_exiting_loop_eq_different_exits_const_compare_known(ptr %s) { 481; CHECK-LABEL: define i1 @multi_exiting_loop_eq_different_exits_const_compare_known( 482; CHECK-SAME: ptr [[S:%.*]]) { 483; CHECK-NEXT: [[ENTRY:.*]]: 484; CHECK-NEXT: br label %[[LOOP_HEADER:.*]] 485; CHECK: [[LOOP_HEADER]]: 486; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] 487; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], 1234 488; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT_1:.*]], label %[[LOOP_LATCH]] 489; CHECK: [[LOOP_LATCH]]: 490; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]] 491; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 492; CHECK-NEXT: [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10 493; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 494; CHECK-NEXT: br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT_2:.*]] 495; CHECK: [[EXIT_1]]: 496; CHECK-NEXT: ret i1 true 497; CHECK: [[EXIT_2]]: 498; CHECK-NEXT: ret i1 true 499; 500entry: 501 br label %loop.header 502 503loop.header: 504 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] 505 %exitcond.not = icmp eq i32 %iv, 1234 506 br i1 %exitcond.not, label %exit.1, label %loop.latch 507 508loop.latch: 509 %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv 510 %0 = load i8, ptr %arrayidx, align 1 511 %latch.c = icmp ult i8 %0, 10 512 %iv.next = add nuw nsw i32 %iv, 1 513 br i1 %latch.c, label %loop.header, label %exit.2 514 515exit.1: 516 %t.1 = icmp ult i32 %iv, 1235 517 ret i1 %t.1 518 519exit.2: 520 %t.2 = icmp ult i32 %iv, 1235 521 ret i1 %t.2 522} 523 524define i1 @multi_exiting_loop_eq_different_exits_2_const_compare_known(ptr %s, i1 %c.1, i1 %c.2) { 525; CHECK-LABEL: define i1 @multi_exiting_loop_eq_different_exits_2_const_compare_known( 526; CHECK-SAME: ptr [[S:%.*]], i1 [[C_1:%.*]], i1 [[C_2:%.*]]) { 527; CHECK-NEXT: [[ENTRY:.*]]: 528; CHECK-NEXT: br label %[[LOOP_HEADER:.*]] 529; CHECK: [[LOOP_HEADER]]: 530; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] 531; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], 1234 532; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT_1:.*]], label %[[ELSE_1:.*]] 533; CHECK: [[ELSE_1]]: 534; CHECK-NEXT: br i1 [[C_1]], label %[[EXIT_1]], label %[[ELSE_2:.*]] 535; CHECK: [[ELSE_2]]: 536; CHECK-NEXT: br i1 [[C_2]], label %[[EXIT_2:.*]], label %[[LOOP_LATCH]] 537; CHECK: [[LOOP_LATCH]]: 538; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]] 539; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 540; CHECK-NEXT: [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10 541; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 542; CHECK-NEXT: br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT_2]] 543; CHECK: [[EXIT_1]]: 544; CHECK-NEXT: ret i1 true 545; CHECK: [[EXIT_2]]: 546; CHECK-NEXT: ret i1 true 547; 548entry: 549 br label %loop.header 550 551loop.header: 552 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] 553 %exitcond.not = icmp eq i32 %iv, 1234 554 br i1 %exitcond.not, label %exit.1, label %else.1 555 556else.1: 557 br i1 %c.1, label %exit.1, label %else.2 558 559else.2: 560 br i1 %c.2, label %exit.2, label %loop.latch 561 562loop.latch: 563 %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv 564 %0 = load i8, ptr %arrayidx, align 1 565 %latch.c = icmp ult i8 %0, 10 566 %iv.next = add nuw nsw i32 %iv, 1 567 br i1 %latch.c, label %loop.header, label %exit.2 568 569exit.1: 570 %t.1 = icmp ult i32 %iv, 1235 571 ret i1 %t.1 572 573exit.2: 574 %t.2 = icmp ult i32 %iv, 1235 575 ret i1 %t.2 576} 577 578 579define i1 @multi_exiting_loop_eq_different_exits_compare_not_known(ptr %s, i32 %N) { 580; CHECK-LABEL: define i1 @multi_exiting_loop_eq_different_exits_compare_not_known( 581; CHECK-SAME: ptr [[S:%.*]], i32 [[N:%.*]]) { 582; CHECK-NEXT: [[ENTRY:.*]]: 583; CHECK-NEXT: br label %[[LOOP_HEADER:.*]] 584; CHECK: [[LOOP_HEADER]]: 585; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] 586; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], [[N]] 587; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT_1:.*]], label %[[LOOP_LATCH]] 588; CHECK: [[LOOP_LATCH]]: 589; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]] 590; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 591; CHECK-NEXT: [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10 592; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 593; CHECK-NEXT: br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT_2:.*]] 594; CHECK: [[EXIT_1]]: 595; CHECK-NEXT: ret i1 false 596; CHECK: [[EXIT_2]]: 597; CHECK-NEXT: ret i1 true 598; 599entry: 600 br label %loop.header 601 602loop.header: 603 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] 604 %exitcond.not = icmp eq i32 %iv, %N 605 br i1 %exitcond.not, label %exit.1, label %loop.latch 606 607loop.latch: 608 %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv 609 %0 = load i8, ptr %arrayidx, align 1 610 %latch.c = icmp ult i8 %0, 10 611 %iv.next = add nuw nsw i32 %iv, 1 612 br i1 %latch.c, label %loop.header, label %exit.2 613 614exit.1: 615 %t.1 = icmp ult i32 %iv, %N 616 ret i1 %t.1 617 618exit.2: 619 %t.2 = icmp ult i32 %iv, %N 620 ret i1 %t.2 621} 622 623define i1 @multi_exiting_loop_eq_different_exits_2_compare_not_known(ptr %s, i32 %N, i1 %c.1, i1 %c.2) { 624; CHECK-LABEL: define i1 @multi_exiting_loop_eq_different_exits_2_compare_not_known( 625; CHECK-SAME: ptr [[S:%.*]], i32 [[N:%.*]], i1 [[C_1:%.*]], i1 [[C_2:%.*]]) { 626; CHECK-NEXT: [[ENTRY:.*]]: 627; CHECK-NEXT: br label %[[LOOP_HEADER:.*]] 628; CHECK: [[LOOP_HEADER]]: 629; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] 630; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], [[N]] 631; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT_1:.*]], label %[[ELSE_1:.*]] 632; CHECK: [[ELSE_1]]: 633; CHECK-NEXT: br i1 [[C_1]], label %[[EXIT_1]], label %[[ELSE_2:.*]] 634; CHECK: [[ELSE_2]]: 635; CHECK-NEXT: br i1 [[C_2]], label %[[EXIT_2:.*]], label %[[LOOP_LATCH]] 636; CHECK: [[LOOP_LATCH]]: 637; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]] 638; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 639; CHECK-NEXT: [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10 640; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 641; CHECK-NEXT: br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT_2]] 642; CHECK: [[EXIT_1]]: 643; CHECK-NEXT: [[T_1:%.*]] = icmp ult i32 [[IV]], [[N]] 644; CHECK-NEXT: ret i1 [[T_1]] 645; CHECK: [[EXIT_2]]: 646; CHECK-NEXT: ret i1 true 647; 648entry: 649 br label %loop.header 650 651loop.header: 652 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] 653 %exitcond.not = icmp eq i32 %iv, %N 654 br i1 %exitcond.not, label %exit.1, label %else.1 655 656else.1: 657 br i1 %c.1, label %exit.1, label %else.2 658 659else.2: 660 br i1 %c.2, label %exit.2, label %loop.latch 661 662loop.latch: 663 %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv 664 %0 = load i8, ptr %arrayidx, align 1 665 %latch.c = icmp ult i8 %0, 10 666 %iv.next = add nuw nsw i32 %iv, 1 667 br i1 %latch.c, label %loop.header, label %exit.2 668 669exit.1: 670 %t.1 = icmp ult i32 %iv, %N 671 ret i1 %t.1 672 673exit.2: 674 %t.2 = icmp ult i32 %iv, %N 675 ret i1 %t.2 676} 677 678define i1 @multi_exiting_loop_ne_different_exits_const_compare_known(ptr %s) { 679; CHECK-LABEL: define i1 @multi_exiting_loop_ne_different_exits_const_compare_known( 680; CHECK-SAME: ptr [[S:%.*]]) { 681; CHECK-NEXT: [[ENTRY:.*]]: 682; CHECK-NEXT: br label %[[LOOP_HEADER:.*]] 683; CHECK: [[LOOP_HEADER]]: 684; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 1, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] 685; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp ne i32 [[IV]], 1234 686; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[LOOP_LATCH]], label %[[EXIT_1:.*]] 687; CHECK: [[LOOP_LATCH]]: 688; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]] 689; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 690; CHECK-NEXT: [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10 691; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 692; CHECK-NEXT: br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT_2:.*]] 693; CHECK: [[EXIT_1]]: 694; CHECK-NEXT: ret i1 true 695; CHECK: [[EXIT_2]]: 696; CHECK-NEXT: ret i1 true 697; 698entry: 699 br label %loop.header 700 701loop.header: 702 %iv = phi i32 [ 1, %entry ], [ %iv.next, %loop.latch ] 703 %exitcond.not = icmp ne i32 %iv, 1234 704 br i1 %exitcond.not, label %loop.latch, label %exit.1 705 706loop.latch: 707 %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv 708 %0 = load i8, ptr %arrayidx, align 1 709 %latch.c = icmp ult i8 %0, 10 710 %iv.next = add nuw nsw i32 %iv, 1 711 br i1 %latch.c, label %loop.header, label %exit.2 712 713exit.1: 714 %t.1 = icmp ult i32 %iv, 1235 715 ret i1 %t.1 716 717exit.2: 718 %t.2 = icmp ult i32 %iv, 1235 719 ret i1 %t.2 720} 721 722define i1 @multi_exiting_loop_ne_different_exits_compare_not_known(ptr %s, i32 %N) { 723; CHECK-LABEL: define i1 @multi_exiting_loop_ne_different_exits_compare_not_known( 724; CHECK-SAME: ptr [[S:%.*]], i32 [[N:%.*]]) { 725; CHECK-NEXT: [[ENTRY:.*]]: 726; CHECK-NEXT: br label %[[LOOP_HEADER:.*]] 727; CHECK: [[LOOP_HEADER]]: 728; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 1, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ] 729; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp ne i32 [[IV]], [[N]] 730; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[LOOP_LATCH]], label %[[EXIT_1:.*]] 731; CHECK: [[LOOP_LATCH]]: 732; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]] 733; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1 734; CHECK-NEXT: [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10 735; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 736; CHECK-NEXT: br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT_2:.*]] 737; CHECK: [[EXIT_1]]: 738; CHECK-NEXT: ret i1 false 739; CHECK: [[EXIT_2]]: 740; CHECK-NEXT: [[T_2:%.*]] = icmp ult i32 [[IV]], [[N]] 741; CHECK-NEXT: ret i1 [[T_2]] 742; 743entry: 744 br label %loop.header 745 746loop.header: 747 %iv = phi i32 [ 1, %entry ], [ %iv.next, %loop.latch ] 748 %exitcond.not = icmp ne i32 %iv, %N 749 br i1 %exitcond.not, label %loop.latch, label %exit.1 750 751loop.latch: 752 %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv 753 %0 = load i8, ptr %arrayidx, align 1 754 %latch.c = icmp ult i8 %0, 10 755 %iv.next = add nuw nsw i32 %iv, 1 756 br i1 %latch.c, label %loop.header, label %exit.2 757 758exit.1: 759 %t.1 = icmp ult i32 %iv, %N 760 ret i1 %t.1 761 762exit.2: 763 %t.2 = icmp ult i32 %iv, %N 764 ret i1 %t.2 765} 766 767define i1 @test_non_dedicated_exit(i16 %n) { 768; CHECK-LABEL: define i1 @test_non_dedicated_exit( 769; CHECK-SAME: i16 [[N:%.*]]) { 770; CHECK-NEXT: [[ENTRY:.*:]] 771; CHECK-NEXT: [[COND:%.*]] = icmp slt i16 [[N]], 1 772; CHECK-NEXT: br i1 [[COND]], label %[[EXIT:.*]], label %[[LOOP_PREHEADER:.*]] 773; CHECK: [[LOOP_PREHEADER]]: 774; CHECK-NEXT: [[SUB:%.*]] = add nsw i16 [[N]], -1 775; CHECK-NEXT: [[EXT:%.*]] = zext nneg i16 [[SUB]] to i32 776; CHECK-NEXT: br label %[[LOOP:.*]] 777; CHECK: [[LOOP]]: 778; CHECK-NEXT: [[INDVAR:%.*]] = phi i32 [ [[INDVAR_INC:%.*]], %[[LOOP_LATCH:.*]] ], [ 0, %[[LOOP_PREHEADER]] ] 779; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INDVAR]], [[EXT]] 780; CHECK-NEXT: br i1 [[EXITCOND]], label %[[EXIT]], label %[[LOOP_LATCH]] 781; CHECK: [[LOOP_LATCH]]: 782; CHECK-NEXT: [[INDVAR_INC]] = add nuw nsw i32 [[INDVAR]], 1 783; CHECK-NEXT: br label %[[LOOP]] 784; CHECK: [[EXIT]]: 785; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i16 [[N]], 0 786; CHECK-NEXT: ret i1 [[CMP]] 787; 788entry: 789 %cond = icmp slt i16 %n, 1 790 br i1 %cond, label %exit, label %loop.preheader 791 792loop.preheader: 793 %sub = add nsw i16 %n, -1 794 %ext = zext nneg i16 %sub to i32 795 br label %loop 796 797loop: 798 %indvar = phi i32 [ %indvar.inc, %loop.latch ], [ 0, %loop.preheader ] 799 %exitcond = icmp eq i32 %indvar, %ext 800 br i1 %exitcond, label %exit, label %loop.latch 801 802loop.latch: 803 %indvar.inc = add nuw nsw i32 %indvar, 1 804 br label %loop 805 806exit: 807 %cmp = icmp sgt i16 %n, 0 808 ret i1 %cmp 809} 810