1 ; RUN: llc < %s -mtriple=x86_64-pc-linux -mattr=+bmi,+lzcnt | FileCheck %s 2 3 ; LZCNT and TZCNT will always produce the operand size when the input operand 4 ; is zero. This test is to verify that we efficiently select LZCNT/TZCNT 5 ; based on the fact that the 'icmp+select' sequence is always redundant 6 ; in every function defined below. 7 8 9 define i16 @test1_ctlz(i16 %v) { 10 %cnt = tail call i16 @llvm.ctlz.i16(i16 %v, i1 true) 11 %tobool = icmp eq i16 %v, 0 12 %cond = select i1 %tobool, i16 16, i16 %cnt 13 ret i16 %cond 14 } 15 ; CHECK-LABEL: test1_ctlz 16 ; CHECK: lzcnt 17 ; CHECK-NEXT: ret 18 19 20 define i32 @test2_ctlz(i32 %v) { 21 %cnt = tail call i32 @llvm.ctlz.i32(i32 %v, i1 true) 22 %tobool = icmp eq i32 %v, 0 23 %cond = select i1 %tobool, i32 32, i32 %cnt 24 ret i32 %cond 25 } 26 ; CHECK-LABEL: test2_ctlz 27 ; CHECK: lzcnt 28 ; CHECK-NEXT: ret 29 30 31 define i64 @test3_ctlz(i64 %v) { 32 %cnt = tail call i64 @llvm.ctlz.i64(i64 %v, i1 true) 33 %tobool = icmp eq i64 %v, 0 34 %cond = select i1 %tobool, i64 64, i64 %cnt 35 ret i64 %cond 36 } 37 ; CHECK-LABEL: test3_ctlz 38 ; CHECK: lzcnt 39 ; CHECK-NEXT: ret 40 41 42 define i16 @test4_ctlz(i16 %v) { 43 %cnt = tail call i16 @llvm.ctlz.i16(i16 %v, i1 true) 44 %tobool = icmp eq i16 0, %v 45 %cond = select i1 %tobool, i16 16, i16 %cnt 46 ret i16 %cond 47 } 48 ; CHECK-LABEL: test4_ctlz 49 ; CHECK: lzcnt 50 ; CHECK-NEXT: ret 51 52 53 define i32 @test5_ctlz(i32 %v) { 54 %cnt = tail call i32 @llvm.ctlz.i32(i32 %v, i1 true) 55 %tobool = icmp eq i32 0, %v 56 %cond = select i1 %tobool, i32 32, i32 %cnt 57 ret i32 %cond 58 } 59 ; CHECK-LABEL: test5_ctlz 60 ; CHECK: lzcnt 61 ; CHECK-NEXT: ret 62 63 64 define i64 @test6_ctlz(i64 %v) { 65 %cnt = tail call i64 @llvm.ctlz.i64(i64 %v, i1 true) 66 %tobool = icmp eq i64 0, %v 67 %cond = select i1 %tobool, i64 64, i64 %cnt 68 ret i64 %cond 69 } 70 ; CHECK-LABEL: test6_ctlz 71 ; CHECK: lzcnt 72 ; CHECK-NEXT: ret 73 74 75 define i16 @test7_ctlz(i16 %v) { 76 %cnt = tail call i16 @llvm.ctlz.i16(i16 %v, i1 true) 77 %tobool = icmp eq i16 0, %v 78 %cond = select i1 %tobool, i16 %cnt, i16 16 79 ret i16 %cond 80 } 81 ; CHECK-LABEL: test7_ctlz 82 ; CHECK: lzcnt 83 ; CHECK-NEXT: ret 84 85 86 define i32 @test8_ctlz(i32 %v) { 87 %cnt = tail call i32 @llvm.ctlz.i32(i32 %v, i1 true) 88 %tobool = icmp eq i32 0, %v 89 %cond = select i1 %tobool, i32 %cnt, i32 32 90 ret i32 %cond 91 } 92 ; CHECK-LABEL: test8_ctlz 93 ; CHECK: lzcnt 94 ; CHECK-NEXT: ret 95 96 97 define i64 @test9_ctlz(i64 %v) { 98 %cnt = tail call i64 @llvm.ctlz.i64(i64 %v, i1 true) 99 %tobool = icmp eq i64 0, %v 100 %cond = select i1 %tobool, i64 %cnt, i64 64 101 ret i64 %cond 102 } 103 ; CHECK-LABEL: test9_ctlz 104 ; CHECK: lzcnt 105 ; CHECK-NEXT: ret 106 107 108 define i16 @test10_ctlz(i16* %ptr) { 109 %v = load i16, i16* %ptr 110 %cnt = tail call i16 @llvm.ctlz.i16(i16 %v, i1 true) 111 %tobool = icmp eq i16 %v, 0 112 %cond = select i1 %tobool, i16 16, i16 %cnt 113 ret i16 %cond 114 } 115 ; CHECK-LABEL: test10_ctlz 116 ; CHECK-NOT: movw 117 ; CHECK: lzcnt 118 ; CHECK-NEXT: ret 119 120 121 define i32 @test11_ctlz(i32* %ptr) { 122 %v = load i32, i32* %ptr 123 %cnt = tail call i32 @llvm.ctlz.i32(i32 %v, i1 true) 124 %tobool = icmp eq i32 %v, 0 125 %cond = select i1 %tobool, i32 32, i32 %cnt 126 ret i32 %cond 127 } 128 ; CHECK-LABEL: test11_ctlz 129 ; CHECK-NOT: movd 130 ; CHECK: lzcnt 131 ; CHECK-NEXT: ret 132 133 134 define i64 @test12_ctlz(i64* %ptr) { 135 %v = load i64, i64* %ptr 136 %cnt = tail call i64 @llvm.ctlz.i64(i64 %v, i1 true) 137 %tobool = icmp eq i64 %v, 0 138 %cond = select i1 %tobool, i64 64, i64 %cnt 139 ret i64 %cond 140 } 141 ; CHECK-LABEL: test12_ctlz 142 ; CHECK-NOT: movq 143 ; CHECK: lzcnt 144 ; CHECK-NEXT: ret 145 146 147 define i16 @test13_ctlz(i16* %ptr) { 148 %v = load i16, i16* %ptr 149 %cnt = tail call i16 @llvm.ctlz.i16(i16 %v, i1 true) 150 %tobool = icmp eq i16 0, %v 151 %cond = select i1 %tobool, i16 16, i16 %cnt 152 ret i16 %cond 153 } 154 ; CHECK-LABEL: test13_ctlz 155 ; CHECK-NOT: movw 156 ; CHECK: lzcnt 157 ; CHECK-NEXT: ret 158 159 160 define i32 @test14_ctlz(i32* %ptr) { 161 %v = load i32, i32* %ptr 162 %cnt = tail call i32 @llvm.ctlz.i32(i32 %v, i1 true) 163 %tobool = icmp eq i32 0, %v 164 %cond = select i1 %tobool, i32 32, i32 %cnt 165 ret i32 %cond 166 } 167 ; CHECK-LABEL: test14_ctlz 168 ; CHECK-NOT: movd 169 ; CHECK: lzcnt 170 ; CHECK-NEXT: ret 171 172 173 define i64 @test15_ctlz(i64* %ptr) { 174 %v = load i64, i64* %ptr 175 %cnt = tail call i64 @llvm.ctlz.i64(i64 %v, i1 true) 176 %tobool = icmp eq i64 0, %v 177 %cond = select i1 %tobool, i64 64, i64 %cnt 178 ret i64 %cond 179 } 180 ; CHECK-LABEL: test15_ctlz 181 ; CHECK-NOT: movq 182 ; CHECK: lzcnt 183 ; CHECK-NEXT: ret 184 185 186 define i16 @test16_ctlz(i16* %ptr) { 187 %v = load i16, i16* %ptr 188 %cnt = tail call i16 @llvm.ctlz.i16(i16 %v, i1 true) 189 %tobool = icmp eq i16 0, %v 190 %cond = select i1 %tobool, i16 %cnt, i16 16 191 ret i16 %cond 192 } 193 ; CHECK-LABEL: test16_ctlz 194 ; CHECK-NOT: movw 195 ; CHECK: lzcnt 196 ; CHECK-NEXT: ret 197 198 199 define i32 @test17_ctlz(i32* %ptr) { 200 %v = load i32, i32* %ptr 201 %cnt = tail call i32 @llvm.ctlz.i32(i32 %v, i1 true) 202 %tobool = icmp eq i32 0, %v 203 %cond = select i1 %tobool, i32 %cnt, i32 32 204 ret i32 %cond 205 } 206 ; CHECK-LABEL: test17_ctlz 207 ; CHECK-NOT: movd 208 ; CHECK: lzcnt 209 ; CHECK-NEXT: ret 210 211 212 define i64 @test18_ctlz(i64* %ptr) { 213 %v = load i64, i64* %ptr 214 %cnt = tail call i64 @llvm.ctlz.i64(i64 %v, i1 true) 215 %tobool = icmp eq i64 0, %v 216 %cond = select i1 %tobool, i64 %cnt, i64 64 217 ret i64 %cond 218 } 219 ; CHECK-LABEL: test18_ctlz 220 ; CHECK-NOT: movq 221 ; CHECK: lzcnt 222 ; CHECK-NEXT: ret 223 224 225 define i16 @test1_cttz(i16 %v) { 226 %cnt = tail call i16 @llvm.cttz.i16(i16 %v, i1 true) 227 %tobool = icmp eq i16 %v, 0 228 %cond = select i1 %tobool, i16 16, i16 %cnt 229 ret i16 %cond 230 } 231 ; CHECK-LABEL: test1_cttz 232 ; CHECK: tzcnt 233 ; CHECK-NEXT: ret 234 235 236 define i32 @test2_cttz(i32 %v) { 237 %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true) 238 %tobool = icmp eq i32 %v, 0 239 %cond = select i1 %tobool, i32 32, i32 %cnt 240 ret i32 %cond 241 } 242 ; CHECK-LABEL: test2_cttz 243 ; CHECK: tzcnt 244 ; CHECK-NEXT: ret 245 246 247 define i64 @test3_cttz(i64 %v) { 248 %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true) 249 %tobool = icmp eq i64 %v, 0 250 %cond = select i1 %tobool, i64 64, i64 %cnt 251 ret i64 %cond 252 } 253 ; CHECK-LABEL: test3_cttz 254 ; CHECK: tzcnt 255 ; CHECK-NEXT: ret 256 257 258 define i16 @test4_cttz(i16 %v) { 259 %cnt = tail call i16 @llvm.cttz.i16(i16 %v, i1 true) 260 %tobool = icmp eq i16 0, %v 261 %cond = select i1 %tobool, i16 16, i16 %cnt 262 ret i16 %cond 263 } 264 ; CHECK-LABEL: test4_cttz 265 ; CHECK: tzcnt 266 ; CHECK-NEXT: ret 267 268 269 define i32 @test5_cttz(i32 %v) { 270 %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true) 271 %tobool = icmp eq i32 0, %v 272 %cond = select i1 %tobool, i32 32, i32 %cnt 273 ret i32 %cond 274 } 275 ; CHECK-LABEL: test5_cttz 276 ; CHECK: tzcnt 277 ; CHECK-NEXT: ret 278 279 280 define i64 @test6_cttz(i64 %v) { 281 %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true) 282 %tobool = icmp eq i64 0, %v 283 %cond = select i1 %tobool, i64 64, i64 %cnt 284 ret i64 %cond 285 } 286 ; CHECK-LABEL: test6_cttz 287 ; CHECK: tzcnt 288 ; CHECK-NEXT: ret 289 290 291 define i16 @test7_cttz(i16 %v) { 292 %cnt = tail call i16 @llvm.cttz.i16(i16 %v, i1 true) 293 %tobool = icmp eq i16 0, %v 294 %cond = select i1 %tobool, i16 %cnt, i16 16 295 ret i16 %cond 296 } 297 ; CHECK-LABEL: test7_cttz 298 ; CHECK: tzcnt 299 ; CHECK-NEXT: ret 300 301 302 define i32 @test8_cttz(i32 %v) { 303 %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true) 304 %tobool = icmp eq i32 0, %v 305 %cond = select i1 %tobool, i32 %cnt, i32 32 306 ret i32 %cond 307 } 308 ; CHECK-LABEL: test8_cttz 309 ; CHECK: tzcnt 310 ; CHECK-NEXT: ret 311 312 313 define i64 @test9_cttz(i64 %v) { 314 %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true) 315 %tobool = icmp eq i64 0, %v 316 %cond = select i1 %tobool, i64 %cnt, i64 64 317 ret i64 %cond 318 } 319 ; CHECK-LABEL: test9_cttz 320 ; CHECK: tzcnt 321 ; CHECK-NEXT: ret 322 323 324 define i16 @test10_cttz(i16* %ptr) { 325 %v = load i16, i16* %ptr 326 %cnt = tail call i16 @llvm.cttz.i16(i16 %v, i1 true) 327 %tobool = icmp eq i16 %v, 0 328 %cond = select i1 %tobool, i16 16, i16 %cnt 329 ret i16 %cond 330 } 331 ; CHECK-LABEL: test10_cttz 332 ; CHECK-NOT: movw 333 ; CHECK: tzcnt 334 ; CHECK-NEXT: ret 335 336 337 define i32 @test11_cttz(i32* %ptr) { 338 %v = load i32, i32* %ptr 339 %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true) 340 %tobool = icmp eq i32 %v, 0 341 %cond = select i1 %tobool, i32 32, i32 %cnt 342 ret i32 %cond 343 } 344 ; CHECK-LABEL: test11_cttz 345 ; CHECK-NOT: movd 346 ; CHECK: tzcnt 347 ; CHECK-NEXT: ret 348 349 350 define i64 @test12_cttz(i64* %ptr) { 351 %v = load i64, i64* %ptr 352 %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true) 353 %tobool = icmp eq i64 %v, 0 354 %cond = select i1 %tobool, i64 64, i64 %cnt 355 ret i64 %cond 356 } 357 ; CHECK-LABEL: test12_cttz 358 ; CHECK-NOT: movq 359 ; CHECK: tzcnt 360 ; CHECK-NEXT: ret 361 362 363 define i16 @test13_cttz(i16* %ptr) { 364 %v = load i16, i16* %ptr 365 %cnt = tail call i16 @llvm.cttz.i16(i16 %v, i1 true) 366 %tobool = icmp eq i16 0, %v 367 %cond = select i1 %tobool, i16 16, i16 %cnt 368 ret i16 %cond 369 } 370 ; CHECK-LABEL: test13_cttz 371 ; CHECK-NOT: movw 372 ; CHECK: tzcnt 373 ; CHECK-NEXT: ret 374 375 376 define i32 @test14_cttz(i32* %ptr) { 377 %v = load i32, i32* %ptr 378 %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true) 379 %tobool = icmp eq i32 0, %v 380 %cond = select i1 %tobool, i32 32, i32 %cnt 381 ret i32 %cond 382 } 383 ; CHECK-LABEL: test14_cttz 384 ; CHECK-NOT: movd 385 ; CHECK: tzcnt 386 ; CHECK-NEXT: ret 387 388 389 define i64 @test15_cttz(i64* %ptr) { 390 %v = load i64, i64* %ptr 391 %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true) 392 %tobool = icmp eq i64 0, %v 393 %cond = select i1 %tobool, i64 64, i64 %cnt 394 ret i64 %cond 395 } 396 ; CHECK-LABEL: test15_cttz 397 ; CHECK-NOT: movq 398 ; CHECK: tzcnt 399 ; CHECK-NEXT: ret 400 401 402 define i16 @test16_cttz(i16* %ptr) { 403 %v = load i16, i16* %ptr 404 %cnt = tail call i16 @llvm.cttz.i16(i16 %v, i1 true) 405 %tobool = icmp eq i16 0, %v 406 %cond = select i1 %tobool, i16 %cnt, i16 16 407 ret i16 %cond 408 } 409 ; CHECK-LABEL: test16_cttz 410 ; CHECK-NOT: movw 411 ; CHECK: tzcnt 412 ; CHECK-NEXT: ret 413 414 415 define i32 @test17_cttz(i32* %ptr) { 416 %v = load i32, i32* %ptr 417 %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true) 418 %tobool = icmp eq i32 0, %v 419 %cond = select i1 %tobool, i32 %cnt, i32 32 420 ret i32 %cond 421 } 422 ; CHECK-LABEL: test17_cttz 423 ; CHECK-NOT: movd 424 ; CHECK: tzcnt 425 ; CHECK-NEXT: ret 426 427 428 define i64 @test18_cttz(i64* %ptr) { 429 %v = load i64, i64* %ptr 430 %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true) 431 %tobool = icmp eq i64 0, %v 432 %cond = select i1 %tobool, i64 %cnt, i64 64 433 ret i64 %cond 434 } 435 ; CHECK-LABEL: test18_cttz 436 ; CHECK-NOT: movq 437 ; CHECK: tzcnt 438 ; CHECK-NEXT: ret 439 440 define i16 @test1b_ctlz(i16 %v) { 441 %cnt = tail call i16 @llvm.ctlz.i16(i16 %v, i1 true) 442 %tobool = icmp ne i16 %v, 0 443 %cond = select i1 %tobool, i16 16, i16 %cnt 444 ret i16 %cond 445 } 446 ; CHECK-LABEL: test1b_ctlz 447 ; CHECK: lzcnt 448 ; CHECK-NEXT: ret 449 450 451 define i32 @test2b_ctlz(i32 %v) { 452 %cnt = tail call i32 @llvm.ctlz.i32(i32 %v, i1 true) 453 %tobool = icmp ne i32 %v, 0 454 %cond = select i1 %tobool, i32 32, i32 %cnt 455 ret i32 %cond 456 } 457 ; CHECK-LABEL: test2b_ctlz 458 ; CHECK: lzcnt 459 ; CHECK-NEXT: ret 460 461 462 define i64 @test3b_ctlz(i64 %v) { 463 %cnt = tail call i64 @llvm.ctlz.i64(i64 %v, i1 true) 464 %tobool = icmp ne i64 %v, 0 465 %cond = select i1 %tobool, i64 64, i64 %cnt 466 ret i64 %cond 467 } 468 ; CHECK-LABEL: test3b_ctlz 469 ; CHECK: lzcnt 470 ; CHECK-NEXT: ret 471 472 473 define i16 @test4b_ctlz(i16 %v) { 474 %cnt = tail call i16 @llvm.ctlz.i16(i16 %v, i1 true) 475 %tobool = icmp ne i16 %v, 0 476 %cond = select i1 %tobool, i16 %cnt, i16 16 477 ret i16 %cond 478 } 479 ; CHECK-LABEL: test4b_ctlz 480 ; CHECK: lzcnt 481 ; CHECK-NEXT: ret 482 483 484 define i32 @test5b_ctlz(i32 %v) { 485 %cnt = tail call i32 @llvm.ctlz.i32(i32 %v, i1 true) 486 %tobool = icmp ne i32 %v, 0 487 %cond = select i1 %tobool, i32 %cnt, i32 32 488 ret i32 %cond 489 } 490 ; CHECK-LABEL: test5b_ctlz 491 ; CHECK: lzcnt 492 ; CHECK-NEXT: ret 493 494 495 define i64 @test6b_ctlz(i64 %v) { 496 %cnt = tail call i64 @llvm.ctlz.i64(i64 %v, i1 true) 497 %tobool = icmp ne i64 %v, 0 498 %cond = select i1 %tobool, i64 %cnt, i64 64 499 ret i64 %cond 500 } 501 ; CHECK-LABEL: test6b_ctlz 502 ; CHECK: lzcnt 503 ; CHECK-NEXT: ret 504 505 506 define i16 @test1b_cttz(i16 %v) { 507 %cnt = tail call i16 @llvm.cttz.i16(i16 %v, i1 true) 508 %tobool = icmp ne i16 %v, 0 509 %cond = select i1 %tobool, i16 16, i16 %cnt 510 ret i16 %cond 511 } 512 ; CHECK-LABEL: test1b_cttz 513 ; CHECK: tzcnt 514 ; CHECK-NEXT: ret 515 516 517 define i32 @test2b_cttz(i32 %v) { 518 %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true) 519 %tobool = icmp ne i32 %v, 0 520 %cond = select i1 %tobool, i32 32, i32 %cnt 521 ret i32 %cond 522 } 523 ; CHECK-LABEL: test2b_cttz 524 ; CHECK: tzcnt 525 ; CHECK-NEXT: ret 526 527 528 define i64 @test3b_cttz(i64 %v) { 529 %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true) 530 %tobool = icmp ne i64 %v, 0 531 %cond = select i1 %tobool, i64 64, i64 %cnt 532 ret i64 %cond 533 } 534 ; CHECK-LABEL: test3b_cttz 535 ; CHECK: tzcnt 536 ; CHECK-NEXT: ret 537 538 539 define i16 @test4b_cttz(i16 %v) { 540 %cnt = tail call i16 @llvm.cttz.i16(i16 %v, i1 true) 541 %tobool = icmp ne i16 %v, 0 542 %cond = select i1 %tobool, i16 %cnt, i16 16 543 ret i16 %cond 544 } 545 ; CHECK-LABEL: test4b_cttz 546 ; CHECK: tzcnt 547 ; CHECK-NEXT: ret 548 549 550 define i32 @test5b_cttz(i32 %v) { 551 %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true) 552 %tobool = icmp ne i32 %v, 0 553 %cond = select i1 %tobool, i32 %cnt, i32 32 554 ret i32 %cond 555 } 556 ; CHECK-LABEL: test5b_cttz 557 ; CHECK: tzcnt 558 ; CHECK-NEXT: ret 559 560 561 define i64 @test6b_cttz(i64 %v) { 562 %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true) 563 %tobool = icmp ne i64 %v, 0 564 %cond = select i1 %tobool, i64 %cnt, i64 64 565 ret i64 %cond 566 } 567 ; CHECK-LABEL: test6b_cttz 568 ; CHECK: tzcnt 569 ; CHECK-NEXT: ret 570 571 572 declare i64 @llvm.cttz.i64(i64, i1) 573 declare i32 @llvm.cttz.i32(i32, i1) 574 declare i16 @llvm.cttz.i16(i16, i1) 575 declare i64 @llvm.ctlz.i64(i64, i1) 576 declare i32 @llvm.ctlz.i32(i32, i1) 577 declare i16 @llvm.ctlz.i16(i16, i1) 578 579