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