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