1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -indvars -S -indvars-predicate-loops=0 < %s | FileCheck %s 3 4target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 5target triple = "x86_64-unknown-linux-gnu" 6 7; General case: without extra knowledge, trunc cannot be eliminated. 8define void @test_00(i64 %start, i32 %n) { 9; 10; CHECK-LABEL: @test_00( 11; CHECK-NEXT: entry: 12; CHECK-NEXT: br label [[LOOP:%.*]] 13; CHECK: loop: 14; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] 15; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 16; CHECK-NEXT: [[NARROW_IV:%.*]] = trunc i64 [[IV]] to i32 17; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[NARROW_IV]], [[N:%.*]] 18; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]] 19; CHECK: exit: 20; CHECK-NEXT: ret void 21; 22entry: 23 br label %loop 24loop: 25 %iv = phi i64 [ %start, %entry ], [ %iv.next, %loop ] 26 %iv.next = add i64 %iv, 1 27 %narrow.iv = trunc i64 %iv to i32 28 %cmp = icmp slt i32 %narrow.iv, %n 29 br i1 %cmp, label %loop, label %exit 30exit: 31 ret void 32} 33 34 35define void @test_01(i32 %n) { 36; 37; CHECK-LABEL: @test_01( 38; CHECK-NEXT: entry: 39; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[N:%.*]], i32 0) 40; CHECK-NEXT: [[TMP0:%.*]] = add nuw i32 [[SMAX]], 1 41; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[TMP0]] to i64 42; CHECK-NEXT: br label [[LOOP:%.*]] 43; CHECK: loop: 44; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] 45; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 46; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], [[WIDE_TRIP_COUNT]] 47; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] 48; CHECK: exit: 49; CHECK-NEXT: ret void 50; 51entry: 52 br label %loop 53loop: 54 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] 55 %iv.next = add i64 %iv, 1 56 %narrow.iv = trunc i64 %iv to i32 57 %cmp = icmp slt i32 %narrow.iv, %n 58 br i1 %cmp, label %loop, label %exit 59exit: 60 ret void 61} 62 63; Max value at which we can eliminate trunc: SINT_MAX - 1. 64define void @test_02(i32 %n) { 65; 66; CHECK-LABEL: @test_02( 67; CHECK-NEXT: entry: 68; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[N:%.*]], i32 2147483646) 69; CHECK-NEXT: [[TMP0:%.*]] = add nuw i32 [[SMAX]], 1 70; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[TMP0]] to i64 71; CHECK-NEXT: br label [[LOOP:%.*]] 72; CHECK: loop: 73; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 2147483646, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] 74; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 75; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], [[WIDE_TRIP_COUNT]] 76; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] 77; CHECK: exit: 78; CHECK-NEXT: ret void 79; 80entry: 81 br label %loop 82loop: 83 %iv = phi i64 [ 2147483646, %entry ], [ %iv.next, %loop ] 84 %iv.next = add i64 %iv, 1 85 %narrow.iv = trunc i64 %iv to i32 86 %cmp = icmp slt i32 %narrow.iv, %n 87 br i1 %cmp, label %loop, label %exit 88exit: 89 ret void 90} 91 92; If we start from SINT_MAX then the predicate is always false. 93define void @test_03(i32 %n) { 94; 95; CHECK-LABEL: @test_03( 96; CHECK-NEXT: entry: 97; CHECK-NEXT: br label [[LOOP:%.*]] 98; CHECK: loop: 99; CHECK-NEXT: br i1 false, label [[LOOP]], label [[EXIT:%.*]] 100; CHECK: exit: 101; CHECK-NEXT: ret void 102; 103entry: 104 br label %loop 105loop: 106 %iv = phi i64 [2147483647, %entry], [%iv.next, %loop] 107 %iv.next = add i64 %iv, 1 108 %narrow.iv = trunc i64 %iv to i32 109 %cmp = icmp slt i32 %narrow.iv, %n 110 br i1 %cmp, label %loop, label %exit 111exit: 112 ret void 113} 114 115; Minimum value at which we can apply the transform: SINT_MIN + 1. 116define void @test_04(i32 %n) { 117; 118; CHECK-LABEL: @test_04( 119; CHECK-NEXT: entry: 120; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[N:%.*]], i32 -2147483647) 121; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[SMAX]], 1 122; CHECK-NEXT: br label [[LOOP:%.*]] 123; CHECK: loop: 124; CHECK-NEXT: [[IV:%.*]] = phi i64 [ -2147483647, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] 125; CHECK-NEXT: [[IV_NEXT]] = add nsw i64 [[IV]], 1 126; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[IV_NEXT]] to i32 127; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[LFTR_WIDEIV]], [[TMP0]] 128; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] 129; CHECK: exit: 130; CHECK-NEXT: ret void 131; 132entry: 133 br label %loop 134loop: 135 %iv = phi i64 [ -2147483647, %entry ], [ %iv.next, %loop ] 136 %iv.next = add i64 %iv, 1 137 %narrow.iv = trunc i64 %iv to i32 138 %cmp = icmp slt i32 %narrow.iv, %n 139 br i1 %cmp, label %loop, label %exit 140exit: 141 ret void 142} 143 144; FIXME: Harmful LFTR should be thrown away. 145define void @test_05(i32 %n) { 146; 147; CHECK-LABEL: @test_05( 148; CHECK-NEXT: entry: 149; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N:%.*]], 1 150; CHECK-NEXT: br label [[LOOP:%.*]] 151; CHECK: loop: 152; CHECK-NEXT: [[IV:%.*]] = phi i64 [ -2147483648, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] 153; CHECK-NEXT: [[IV_NEXT]] = add nsw i64 [[IV]], 1 154; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[IV_NEXT]] to i32 155; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[LFTR_WIDEIV]], [[TMP0]] 156; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] 157; CHECK: exit: 158; CHECK-NEXT: ret void 159; 160entry: 161 br label %loop 162loop: 163 %iv = phi i64 [ -2147483648, %entry ], [ %iv.next, %loop ] 164 %iv.next = add i64 %iv, 1 165 %narrow.iv = trunc i64 %iv to i32 166 %cmp = icmp slt i32 %narrow.iv, %n 167 br i1 %cmp, label %loop, label %exit 168exit: 169 ret void 170} 171 172; Trunc changes the actual value of the IV, so it is invalid to remove it: SINT_MIN - 1. 173define void @test_06(i32 %n) { 174; 175; CHECK-LABEL: @test_06( 176; CHECK-NEXT: entry: 177; CHECK-NEXT: br label [[LOOP:%.*]] 178; CHECK: loop: 179; CHECK-NEXT: br i1 false, label [[LOOP]], label [[EXIT:%.*]] 180; CHECK: exit: 181; CHECK-NEXT: ret void 182; 183entry: 184 br label %loop 185loop: 186 %iv = phi i64 [ -2147483649, %entry ], [ %iv.next, %loop ] 187 %iv.next = add i64 %iv, 1 188 %narrow.iv = trunc i64 %iv to i32 189 %cmp = icmp slt i32 %narrow.iv, %n 190 br i1 %cmp, label %loop, label %exit 191exit: 192 ret void 193} 194 195; General case: without extra knowledge, trunc cannot be eliminated. 196define void @test_00_unsigned(i64 %start, i32 %n) { 197; CHECK-LABEL: @test_00_unsigned( 198; CHECK-NEXT: entry: 199; CHECK-NEXT: br label [[LOOP:%.*]] 200; CHECK: loop: 201; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] 202; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 203; CHECK-NEXT: [[NARROW_IV:%.*]] = trunc i64 [[IV]] to i32 204; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[NARROW_IV]], [[N:%.*]] 205; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]] 206; CHECK: exit: 207; CHECK-NEXT: ret void 208; 209entry: 210 br label %loop 211loop: 212 %iv = phi i64 [ %start, %entry ], [ %iv.next, %loop ] 213 %iv.next = add i64 %iv, 1 214 %narrow.iv = trunc i64 %iv to i32 215 %cmp = icmp ult i32 %narrow.iv, %n 216 br i1 %cmp, label %loop, label %exit 217exit: 218 ret void 219} 220 221; FIXME: Harmful LFTR should be thrown away. 222define void @test_01_unsigned(i32 %n) { 223; CHECK-LABEL: @test_01_unsigned( 224; CHECK-NEXT: entry: 225; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N:%.*]], 1 226; CHECK-NEXT: br label [[LOOP:%.*]] 227; CHECK: loop: 228; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] 229; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 230; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[IV_NEXT]] to i32 231; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[LFTR_WIDEIV]], [[TMP0]] 232; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] 233; CHECK: exit: 234; CHECK-NEXT: ret void 235; 236entry: 237 br label %loop 238loop: 239 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] 240 %iv.next = add i64 %iv, 1 241 %narrow.iv = trunc i64 %iv to i32 242 %cmp = icmp ult i32 %narrow.iv, %n 243 br i1 %cmp, label %loop, label %exit 244exit: 245 ret void 246} 247 248; Max value at which we can eliminate trunc: UINT_MAX - 1. 249define void @test_02_unsigned(i32 %n) { 250; CHECK-LABEL: @test_02_unsigned( 251; CHECK-NEXT: entry: 252; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 -2) 253; CHECK-NEXT: [[TMP0:%.*]] = add nsw i32 [[UMAX]], 1 254; CHECK-NEXT: br label [[LOOP:%.*]] 255; CHECK: loop: 256; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 4294967294, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] 257; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 258; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[IV_NEXT]] to i32 259; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[LFTR_WIDEIV]], [[TMP0]] 260; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] 261; CHECK: exit: 262; CHECK-NEXT: ret void 263; 264entry: 265 br label %loop 266loop: 267 %iv = phi i64 [ 4294967294, %entry ], [ %iv.next, %loop ] 268 %iv.next = add i64 %iv, 1 269 %narrow.iv = trunc i64 %iv to i32 270 %cmp = icmp ult i32 %narrow.iv, %n 271 br i1 %cmp, label %loop, label %exit 272exit: 273 ret void 274} 275 276; If we start from UINT_MAX then the predicate is always false. 277define void @test_03_unsigned(i32 %n) { 278; CHECK-LABEL: @test_03_unsigned( 279; CHECK-NEXT: entry: 280; CHECK-NEXT: br label [[LOOP:%.*]] 281; CHECK: loop: 282; CHECK-NEXT: br i1 false, label [[LOOP]], label [[EXIT:%.*]] 283; CHECK: exit: 284; CHECK-NEXT: ret void 285; 286entry: 287 br label %loop 288loop: 289 %iv = phi i64 [ 4294967295, %entry ], [ %iv.next, %loop ] 290 %iv.next = add i64 %iv, 1 291 %narrow.iv = trunc i64 %iv to i32 292 %cmp = icmp ult i32 %narrow.iv, %n 293 br i1 %cmp, label %loop, label %exit 294exit: 295 ret void 296} 297 298; Minimum value at which we can apply the transform: UINT_MIN. 299define void @test_04_unsigned(i32 %n) { 300; CHECK-LABEL: @test_04_unsigned( 301; CHECK-NEXT: entry: 302; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N:%.*]], 1 303; CHECK-NEXT: br label [[LOOP:%.*]] 304; CHECK: loop: 305; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] 306; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 307; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[IV_NEXT]] to i32 308; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[LFTR_WIDEIV]], [[TMP0]] 309; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] 310; CHECK: exit: 311; CHECK-NEXT: ret void 312; 313entry: 314 br label %loop 315loop: 316 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] 317 %iv.next = add i64 %iv, 1 318 %narrow.iv = trunc i64 %iv to i32 319 %cmp = icmp ult i32 %narrow.iv, %n 320 br i1 %cmp, label %loop, label %exit 321exit: 322 ret void 323} 324 325; Start from 1. 326define void @test_05_unsigned(i32 %n) { 327; CHECK-LABEL: @test_05_unsigned( 328; CHECK-NEXT: entry: 329; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1) 330; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[UMAX]], 1 331; CHECK-NEXT: br label [[LOOP:%.*]] 332; CHECK: loop: 333; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 1, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] 334; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 335; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[IV_NEXT]] to i32 336; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[LFTR_WIDEIV]], [[TMP0]] 337; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] 338; CHECK: exit: 339; CHECK-NEXT: ret void 340; 341entry: 342 br label %loop 343loop: 344 %iv = phi i64 [ 1, %entry ], [ %iv.next, %loop ] 345 %iv.next = add i64 %iv, 1 346 %narrow.iv = trunc i64 %iv to i32 347 %cmp = icmp ult i32 %narrow.iv, %n 348 br i1 %cmp, label %loop, label %exit 349exit: 350 ret void 351} 352 353; Trunc changes the actual value of the IV, so it is invalid to remove it: UINT_MIN - 1. 354define void @test_06_unsigned(i32 %n) { 355; CHECK-LABEL: @test_06_unsigned( 356; CHECK-NEXT: entry: 357; CHECK-NEXT: br label [[LOOP:%.*]] 358; CHECK: loop: 359; CHECK-NEXT: br i1 false, label [[LOOP]], label [[EXIT:%.*]] 360; CHECK: exit: 361; CHECK-NEXT: ret void 362; 363entry: 364 br label %loop 365loop: 366 %iv = phi i64 [ -1, %entry ], [ %iv.next, %loop ] 367 %iv.next = add i64 %iv, 1 368 %narrow.iv = trunc i64 %iv to i32 369 %cmp = icmp ult i32 %narrow.iv, %n 370 br i1 %cmp, label %loop, label %exit 371exit: 372 ret void 373} 374 375; Do not eliminate trunc if it is used by something different from icmp. 376define void @test_07(i32* %p, i32 %n) { 377; CHECK-LABEL: @test_07( 378; CHECK-NEXT: entry: 379; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[N:%.*]], i32 0) 380; CHECK-NEXT: [[TMP0:%.*]] = add nuw i32 [[SMAX]], 1 381; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[TMP0]] to i64 382; CHECK-NEXT: br label [[LOOP:%.*]] 383; CHECK: loop: 384; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] 385; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 386; CHECK-NEXT: [[NARROW_IV:%.*]] = trunc i64 [[IV]] to i32 387; CHECK-NEXT: store i32 [[NARROW_IV]], i32* [[P:%.*]], align 4 388; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], [[WIDE_TRIP_COUNT]] 389; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] 390; CHECK: exit: 391; CHECK-NEXT: ret void 392; 393entry: 394 br label %loop 395loop: 396 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] 397 %iv.next = add i64 %iv, 1 398 %narrow.iv = trunc i64 %iv to i32 399 store i32 %narrow.iv, i32* %p 400 %cmp = icmp slt i32 %narrow.iv, %n 401 br i1 %cmp, label %loop, label %exit 402exit: 403 ret void 404} 405 406; Check that we can eliminate both signed and unsigned compare. 407define void @test_08(i32 %n) { 408; CHECK-LABEL: @test_08( 409; CHECK-NEXT: entry: 410; CHECK-NEXT: [[ZEXT:%.*]] = zext i32 [[N:%.*]] to i64 411; CHECK-NEXT: [[SEXT:%.*]] = sext i32 [[N]] to i64 412; CHECK-NEXT: br label [[LOOP:%.*]] 413; CHECK: loop: 414; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 1, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] 415; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 416; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i64 [[IV]], [[SEXT]] 417; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i64 [[IV]], [[ZEXT]] 418; CHECK-NEXT: [[CMP:%.*]] = and i1 [[TMP0]], [[TMP1]] 419; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]] 420; CHECK: exit: 421; CHECK-NEXT: ret void 422; 423entry: 424 br label %loop 425loop: 426 %iv = phi i64 [ 1, %entry ], [ %iv.next, %loop ] 427 %iv.next = add i64 %iv, 1 428 %narrow.iv = trunc i64 %iv to i32 429 %cmp1 = icmp slt i32 %narrow.iv, %n 430 %cmp2 = icmp ult i32 %narrow.iv, %n 431 %cmp = and i1 %cmp1, %cmp2 432 br i1 %cmp, label %loop, label %exit 433exit: 434 ret void 435} 436 437; Widen NE as unsigned. 438define void @test_09(i32 %n) { 439; CHECK-LABEL: @test_09( 440; CHECK-NEXT: entry: 441; CHECK-NEXT: [[ZEXT:%.*]] = zext i32 [[N:%.*]] to i64 442; CHECK-NEXT: br label [[LOOP:%.*]] 443; CHECK: loop: 444; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] 445; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 446; CHECK-NEXT: [[TMP0:%.*]] = icmp ne i64 [[IV]], [[ZEXT]] 447; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]] 448; CHECK: exit: 449; CHECK-NEXT: ret void 450; 451entry: 452 br label %loop 453loop: 454 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] 455 %iv.next = add i64 %iv, 1 456 %narrow.iv = trunc i64 %iv to i32 457 %cmp = icmp ne i32 %narrow.iv, %n 458 br i1 %cmp, label %loop, label %exit 459exit: 460 ret void 461} 462 463; Widen NE as signed. 464define void @test_10(i32 %n) { 465; CHECK-LABEL: @test_10( 466; CHECK-NEXT: entry: 467; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N:%.*]], 100 468; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64 469; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP1]], i64 90) 470; CHECK-NEXT: [[TMP2:%.*]] = add nuw nsw i64 [[UMIN]], -99 471; CHECK-NEXT: br label [[LOOP:%.*]] 472; CHECK: loop: 473; CHECK-NEXT: [[IV:%.*]] = phi i64 [ -100, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] 474; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 475; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], [[TMP2]] 476; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] 477; CHECK: exit: 478; CHECK-NEXT: ret void 479; 480entry: 481 br label %loop 482loop: 483 %iv = phi i64 [ -100, %entry ], [ %iv.next, %loop ] 484 %iv.next = add i64 %iv, 1 485 %narrow.iv = trunc i64 %iv to i32 486 %trunccmp = icmp ne i32 %narrow.iv, %n 487 %negcmp = icmp slt i64 %iv, -10 488 %cmp = and i1 %trunccmp, %negcmp 489 br i1 %cmp, label %loop, label %exit 490exit: 491 ret void 492} 493 494define void @test_11() { 495; CHECK-LABEL: @test_11( 496; CHECK-NEXT: br label [[BB1:%.*]] 497; CHECK: bb1: 498; CHECK-NEXT: br i1 undef, label [[BB2:%.*]], label [[BB6:%.*]] 499; CHECK: bb2: 500; CHECK-NEXT: br i1 undef, label [[BB3:%.*]], label [[BB4:%.*]] 501; CHECK: bb3: 502; CHECK-NEXT: br label [[BB4]] 503; CHECK: bb4: 504; CHECK-NEXT: br label [[BB6]] 505; CHECK: bb5: 506; CHECK-NEXT: [[_TMP24:%.*]] = icmp slt i16 undef, 0 507; CHECK-NEXT: br i1 [[_TMP24]], label [[BB5:%.*]], label [[BB5]] 508; CHECK: bb6: 509; CHECK-NEXT: br i1 false, label [[BB1]], label [[BB7:%.*]] 510; CHECK: bb7: 511; CHECK-NEXT: ret void 512; 513 br label %bb1 514 515bb1: ; preds = %bb6, %0 516 %e.5.0 = phi i32 [ 0, %0 ], [ %_tmp32, %bb6 ] 517 br i1 undef, label %bb2, label %bb6 518 519bb2: ; preds = %bb1 520 %_tmp15 = trunc i32 %e.5.0 to i16 521 br i1 undef, label %bb3, label %bb4 522 523bb3: ; preds = %bb2 524 br label %bb4 525 526bb4: ; preds = %bb3, %bb2 527 br label %bb6 528 529bb5: ; preds = %bb5, %bb5 530 %_tmp24 = icmp slt i16 %_tmp15, 0 531 br i1 %_tmp24, label %bb5, label %bb5 532 533bb6: ; preds = %bb4, %bb1 534 %_tmp32 = add nuw nsw i32 %e.5.0, 1 535 br i1 false, label %bb1, label %bb7 536 537bb7: ; preds = %bb6 538 ret void 539} 540 541; Show that we can turn signed comparison to unsigned and use zext while 542; comparing non-negative values. 543define void @test_12(i32* %p) { 544; CHECK-LABEL: @test_12( 545; CHECK-NEXT: entry: 546; CHECK-NEXT: [[N:%.*]] = load i32, i32* [[P:%.*]], align 4, [[RNG0:!range !.*]] 547; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[N]], i32 1) 548; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64 549; CHECK-NEXT: br label [[LOOP:%.*]] 550; CHECK: loop: 551; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] 552; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 553; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], [[WIDE_TRIP_COUNT]] 554; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] 555; CHECK: exit: 556; CHECK-NEXT: ret void 557; 558entry: 559 %n = load i32, i32* %p, !range !0 560 br label %loop 561loop: 562 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] 563 %iv.next = add i64 %iv, 1 564 %narrow.iv = trunc i64 %iv.next to i32 565 %cmp = icmp slt i32 %narrow.iv, %n 566 br i1 %cmp, label %loop, label %exit 567exit: 568 ret void 569} 570 571define void @test_13a(i32 %n) { 572; 573; CHECK-LABEL: @test_13a( 574; CHECK-NEXT: entry: 575; CHECK-NEXT: [[ZEXT:%.*]] = zext i32 1024 to i64 576; CHECK-NEXT: br label [[LOOP:%.*]] 577; CHECK: loop: 578; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] 579; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 2 580; CHECK-NEXT: [[TMP0:%.*]] = icmp ne i64 [[IV]], [[ZEXT]] 581; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]] 582; CHECK: exit: 583; CHECK-NEXT: ret void 584; 585entry: 586 br label %loop 587loop: 588 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] 589 %iv.next = add nsw nuw i64 %iv, 2 590 %narrow.iv = trunc i64 %iv to i32 591 %cmp = icmp ne i32 1024, %narrow.iv 592 br i1 %cmp, label %loop, label %exit 593exit: 594 ret void 595} 596 597define void @test_13b(i32 %n) { 598; 599; CHECK-LABEL: @test_13b( 600; CHECK-NEXT: entry: 601; CHECK-NEXT: [[ZEXT:%.*]] = zext i32 1024 to i64 602; CHECK-NEXT: br label [[LOOP:%.*]] 603; CHECK: loop: 604; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] 605; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 2 606; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i64 [[IV]], [[ZEXT]] 607; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]] 608; CHECK: exit: 609; CHECK-NEXT: ret void 610; 611entry: 612 br label %loop 613loop: 614 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] 615 %iv.next = add nsw nuw i64 %iv, 2 616 %narrow.iv = trunc i64 %iv to i32 617 %cmp = icmp ugt i32 1024, %narrow.iv 618 br i1 %cmp, label %loop, label %exit 619exit: 620 ret void 621} 622 623define void @test_13c(i32 %n) { 624; 625; CHECK-LABEL: @test_13c( 626; CHECK-NEXT: entry: 627; CHECK-NEXT: [[ZEXT:%.*]] = zext i32 1024 to i64 628; CHECK-NEXT: br label [[LOOP:%.*]] 629; CHECK: loop: 630; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] 631; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 2 632; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i64 [[IV]], [[ZEXT]] 633; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]] 634; CHECK: exit: 635; CHECK-NEXT: ret void 636; 637entry: 638 br label %loop 639loop: 640 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] 641 %iv.next = add nsw nuw i64 %iv, 2 642 %narrow.iv = trunc i64 %iv to i32 643 %cmp = icmp sgt i32 1024, %narrow.iv 644 br i1 %cmp, label %loop, label %exit 645exit: 646 ret void 647} 648 649define void @test_13d(i32 %n) { 650; 651; CHECK-LABEL: @test_13d( 652; CHECK-NEXT: entry: 653; CHECK-NEXT: [[SEXT:%.*]] = sext i32 1024 to i64 654; CHECK-NEXT: br label [[LOOP:%.*]] 655; CHECK: loop: 656; CHECK-NEXT: [[IV:%.*]] = phi i64 [ -20, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] 657; CHECK-NEXT: [[IV_NEXT]] = add nsw i64 [[IV]], 2 658; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i64 [[IV]], [[SEXT]] 659; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP]], label [[EXIT:%.*]] 660; CHECK: exit: 661; CHECK-NEXT: ret void 662; 663entry: 664 br label %loop 665loop: 666 %iv = phi i64 [ -20, %entry ], [ %iv.next, %loop ] 667 %iv.next = add nsw i64 %iv, 2 668 %narrow.iv = trunc i64 %iv to i32 669 %cmp = icmp sgt i32 1024, %narrow.iv 670 br i1 %cmp, label %loop, label %exit 671exit: 672 ret void 673} 674 675!0 = !{i32 0, i32 1000} 676