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 9define 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 20define 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 31define 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 42define 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 53define 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 64define 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 75define 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 86define 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 97define 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 108define 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 121define 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 134define 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 147define 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 160define 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 173define 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 186define 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 199define 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 212define 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 225define 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 236define 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 247define 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 258define 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 269define 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 280define 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 291define 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 302define 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 313define 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 324define 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 337define 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 350define 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 363define 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 376define 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 389define 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 402define 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 415define 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 428define 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 440define 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 451define 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 462define 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 473define 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 484define 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 495define 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 506define 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 517define 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 528define 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 539define 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 550define 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 561define 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 572declare i64 @llvm.cttz.i64(i64, i1) 573declare i32 @llvm.cttz.i32(i32, i1) 574declare i16 @llvm.cttz.i16(i16, i1) 575declare i64 @llvm.ctlz.i64(i64, i1) 576declare i32 @llvm.ctlz.i32(i32, i1) 577declare i16 @llvm.ctlz.i16(i16, i1) 578 579