1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s 3 4; *Please* keep in sync with test/CodeGen/X86/extract-lowbits.ll 5 6; https://bugs.llvm.org/show_bug.cgi?id=36419 7; https://bugs.llvm.org/show_bug.cgi?id=37603 8; https://bugs.llvm.org/show_bug.cgi?id=37610 9 10; Patterns: 11; a) x & (1 << nbits) - 1 12; b) x & ~(-1 << nbits) 13; c) x & (-1 >> (32 - y)) 14; d) x << (32 - y) >> (32 - y) 15; are equivalent. 16 17; ---------------------------------------------------------------------------- ; 18; Pattern a. 32-bit 19; ---------------------------------------------------------------------------- ; 20 21define i32 @bzhi32_a0(i32 %val, i32 %numlowbits) nounwind { 22; CHECK-LABEL: bzhi32_a0: 23; CHECK: // %bb.0: 24; CHECK-NEXT: mov w8, #1 // =0x1 25; CHECK-NEXT: lsl w8, w8, w1 26; CHECK-NEXT: sub w8, w8, #1 27; CHECK-NEXT: and w0, w8, w0 28; CHECK-NEXT: ret 29 %onebit = shl i32 1, %numlowbits 30 %mask = add nsw i32 %onebit, -1 31 %masked = and i32 %mask, %val 32 ret i32 %masked 33} 34 35define i32 @bzhi32_a1_indexzext(i32 %val, i8 zeroext %numlowbits) nounwind { 36; CHECK-LABEL: bzhi32_a1_indexzext: 37; CHECK: // %bb.0: 38; CHECK-NEXT: mov w8, #1 // =0x1 39; CHECK-NEXT: lsl w8, w8, w1 40; CHECK-NEXT: sub w8, w8, #1 41; CHECK-NEXT: and w0, w8, w0 42; CHECK-NEXT: ret 43 %conv = zext i8 %numlowbits to i32 44 %onebit = shl i32 1, %conv 45 %mask = add nsw i32 %onebit, -1 46 %masked = and i32 %mask, %val 47 ret i32 %masked 48} 49 50define i32 @bzhi32_a2_load(ptr %w, i32 %numlowbits) nounwind { 51; CHECK-LABEL: bzhi32_a2_load: 52; CHECK: // %bb.0: 53; CHECK-NEXT: mov w8, #1 // =0x1 54; CHECK-NEXT: ldr w9, [x0] 55; CHECK-NEXT: lsl w8, w8, w1 56; CHECK-NEXT: sub w8, w8, #1 57; CHECK-NEXT: and w0, w8, w9 58; CHECK-NEXT: ret 59 %val = load i32, ptr %w 60 %onebit = shl i32 1, %numlowbits 61 %mask = add nsw i32 %onebit, -1 62 %masked = and i32 %mask, %val 63 ret i32 %masked 64} 65 66define i32 @bzhi32_a3_load_indexzext(ptr %w, i8 zeroext %numlowbits) nounwind { 67; CHECK-LABEL: bzhi32_a3_load_indexzext: 68; CHECK: // %bb.0: 69; CHECK-NEXT: mov w8, #1 // =0x1 70; CHECK-NEXT: ldr w9, [x0] 71; CHECK-NEXT: lsl w8, w8, w1 72; CHECK-NEXT: sub w8, w8, #1 73; CHECK-NEXT: and w0, w8, w9 74; CHECK-NEXT: ret 75 %val = load i32, ptr %w 76 %conv = zext i8 %numlowbits to i32 77 %onebit = shl i32 1, %conv 78 %mask = add nsw i32 %onebit, -1 79 %masked = and i32 %mask, %val 80 ret i32 %masked 81} 82 83define i32 @bzhi32_a4_commutative(i32 %val, i32 %numlowbits) nounwind { 84; CHECK-LABEL: bzhi32_a4_commutative: 85; CHECK: // %bb.0: 86; CHECK-NEXT: mov w8, #1 // =0x1 87; CHECK-NEXT: lsl w8, w8, w1 88; CHECK-NEXT: sub w8, w8, #1 89; CHECK-NEXT: and w0, w0, w8 90; CHECK-NEXT: ret 91 %onebit = shl i32 1, %numlowbits 92 %mask = add nsw i32 %onebit, -1 93 %masked = and i32 %val, %mask ; swapped order 94 ret i32 %masked 95} 96 97; 64-bit 98 99define i64 @bzhi64_a0(i64 %val, i64 %numlowbits) nounwind { 100; CHECK-LABEL: bzhi64_a0: 101; CHECK: // %bb.0: 102; CHECK-NEXT: mov w8, #1 // =0x1 103; CHECK-NEXT: lsl x8, x8, x1 104; CHECK-NEXT: sub x8, x8, #1 105; CHECK-NEXT: and x0, x8, x0 106; CHECK-NEXT: ret 107 %onebit = shl i64 1, %numlowbits 108 %mask = add nsw i64 %onebit, -1 109 %masked = and i64 %mask, %val 110 ret i64 %masked 111} 112 113; Check that we don't throw away the vreg_width-1 mask if not using shifts 114define i64 @bzhi64_a0_masked(i64 %val, i64 %numlowbits) nounwind { 115; CHECK-LABEL: bzhi64_a0_masked: 116; CHECK: // %bb.0: 117; CHECK-NEXT: mov w8, #1 // =0x1 118; CHECK-NEXT: lsl x8, x8, x1 119; CHECK-NEXT: sub x8, x8, #1 120; CHECK-NEXT: and x0, x8, x0 121; CHECK-NEXT: ret 122 %numlowbits.masked = and i64 %numlowbits, 63 123 %onebit = shl i64 1, %numlowbits.masked 124 %mask = add nsw i64 %onebit, -1 125 %masked = and i64 %mask, %val 126 ret i64 %masked 127} 128 129define i64 @bzhi64_a1_indexzext(i64 %val, i8 zeroext %numlowbits) nounwind { 130; CHECK-LABEL: bzhi64_a1_indexzext: 131; CHECK: // %bb.0: 132; CHECK-NEXT: mov w8, #1 // =0x1 133; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 134; CHECK-NEXT: lsl x8, x8, x1 135; CHECK-NEXT: sub x8, x8, #1 136; CHECK-NEXT: and x0, x8, x0 137; CHECK-NEXT: ret 138 %conv = zext i8 %numlowbits to i64 139 %onebit = shl i64 1, %conv 140 %mask = add nsw i64 %onebit, -1 141 %masked = and i64 %mask, %val 142 ret i64 %masked 143} 144 145define i64 @bzhi64_a2_load(ptr %w, i64 %numlowbits) nounwind { 146; CHECK-LABEL: bzhi64_a2_load: 147; CHECK: // %bb.0: 148; CHECK-NEXT: mov w8, #1 // =0x1 149; CHECK-NEXT: ldr x9, [x0] 150; CHECK-NEXT: lsl x8, x8, x1 151; CHECK-NEXT: sub x8, x8, #1 152; CHECK-NEXT: and x0, x8, x9 153; CHECK-NEXT: ret 154 %val = load i64, ptr %w 155 %onebit = shl i64 1, %numlowbits 156 %mask = add nsw i64 %onebit, -1 157 %masked = and i64 %mask, %val 158 ret i64 %masked 159} 160 161define i64 @bzhi64_a3_load_indexzext(ptr %w, i8 zeroext %numlowbits) nounwind { 162; CHECK-LABEL: bzhi64_a3_load_indexzext: 163; CHECK: // %bb.0: 164; CHECK-NEXT: mov w8, #1 // =0x1 165; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 166; CHECK-NEXT: ldr x9, [x0] 167; CHECK-NEXT: lsl x8, x8, x1 168; CHECK-NEXT: sub x8, x8, #1 169; CHECK-NEXT: and x0, x8, x9 170; CHECK-NEXT: ret 171 %val = load i64, ptr %w 172 %conv = zext i8 %numlowbits to i64 173 %onebit = shl i64 1, %conv 174 %mask = add nsw i64 %onebit, -1 175 %masked = and i64 %mask, %val 176 ret i64 %masked 177} 178 179define i64 @bzhi64_a4_commutative(i64 %val, i64 %numlowbits) nounwind { 180; CHECK-LABEL: bzhi64_a4_commutative: 181; CHECK: // %bb.0: 182; CHECK-NEXT: mov w8, #1 // =0x1 183; CHECK-NEXT: lsl x8, x8, x1 184; CHECK-NEXT: sub x8, x8, #1 185; CHECK-NEXT: and x0, x0, x8 186; CHECK-NEXT: ret 187 %onebit = shl i64 1, %numlowbits 188 %mask = add nsw i64 %onebit, -1 189 %masked = and i64 %val, %mask ; swapped order 190 ret i64 %masked 191} 192 193; ---------------------------------------------------------------------------- ; 194; Pattern b. 32-bit 195; ---------------------------------------------------------------------------- ; 196 197define i32 @bzhi32_b0(i32 %val, i32 %numlowbits) nounwind { 198; CHECK-LABEL: bzhi32_b0: 199; CHECK: // %bb.0: 200; CHECK-NEXT: mov w8, #-1 // =0xffffffff 201; CHECK-NEXT: lsl w8, w8, w1 202; CHECK-NEXT: bic w0, w0, w8 203; CHECK-NEXT: ret 204 %notmask = shl i32 -1, %numlowbits 205 %mask = xor i32 %notmask, -1 206 %masked = and i32 %mask, %val 207 ret i32 %masked 208} 209 210define i32 @bzhi32_b1_indexzext(i32 %val, i8 zeroext %numlowbits) nounwind { 211; CHECK-LABEL: bzhi32_b1_indexzext: 212; CHECK: // %bb.0: 213; CHECK-NEXT: mov w8, #-1 // =0xffffffff 214; CHECK-NEXT: lsl w8, w8, w1 215; CHECK-NEXT: bic w0, w0, w8 216; CHECK-NEXT: ret 217 %conv = zext i8 %numlowbits to i32 218 %notmask = shl i32 -1, %conv 219 %mask = xor i32 %notmask, -1 220 %masked = and i32 %mask, %val 221 ret i32 %masked 222} 223 224define i32 @bzhi32_b2_load(ptr %w, i32 %numlowbits) nounwind { 225; CHECK-LABEL: bzhi32_b2_load: 226; CHECK: // %bb.0: 227; CHECK-NEXT: mov w8, #-1 // =0xffffffff 228; CHECK-NEXT: ldr w9, [x0] 229; CHECK-NEXT: lsl w8, w8, w1 230; CHECK-NEXT: bic w0, w9, w8 231; CHECK-NEXT: ret 232 %val = load i32, ptr %w 233 %notmask = shl i32 -1, %numlowbits 234 %mask = xor i32 %notmask, -1 235 %masked = and i32 %mask, %val 236 ret i32 %masked 237} 238 239define i32 @bzhi32_b3_load_indexzext(ptr %w, i8 zeroext %numlowbits) nounwind { 240; CHECK-LABEL: bzhi32_b3_load_indexzext: 241; CHECK: // %bb.0: 242; CHECK-NEXT: mov w8, #-1 // =0xffffffff 243; CHECK-NEXT: ldr w9, [x0] 244; CHECK-NEXT: lsl w8, w8, w1 245; CHECK-NEXT: bic w0, w9, w8 246; CHECK-NEXT: ret 247 %val = load i32, ptr %w 248 %conv = zext i8 %numlowbits to i32 249 %notmask = shl i32 -1, %conv 250 %mask = xor i32 %notmask, -1 251 %masked = and i32 %mask, %val 252 ret i32 %masked 253} 254 255define i32 @bzhi32_b4_commutative(i32 %val, i32 %numlowbits) nounwind { 256; CHECK-LABEL: bzhi32_b4_commutative: 257; CHECK: // %bb.0: 258; CHECK-NEXT: mov w8, #-1 // =0xffffffff 259; CHECK-NEXT: lsl w8, w8, w1 260; CHECK-NEXT: bic w0, w0, w8 261; CHECK-NEXT: ret 262 %notmask = shl i32 -1, %numlowbits 263 %mask = xor i32 %notmask, -1 264 %masked = and i32 %val, %mask ; swapped order 265 ret i32 %masked 266} 267 268; 64-bit 269 270define i64 @bzhi64_b0(i64 %val, i64 %numlowbits) nounwind { 271; CHECK-LABEL: bzhi64_b0: 272; CHECK: // %bb.0: 273; CHECK-NEXT: mov x8, #-1 // =0xffffffffffffffff 274; CHECK-NEXT: lsl x8, x8, x1 275; CHECK-NEXT: bic x0, x0, x8 276; CHECK-NEXT: ret 277 %notmask = shl i64 -1, %numlowbits 278 %mask = xor i64 %notmask, -1 279 %masked = and i64 %mask, %val 280 ret i64 %masked 281} 282 283define i64 @bzhi64_b1_indexzext(i64 %val, i8 zeroext %numlowbits) nounwind { 284; CHECK-LABEL: bzhi64_b1_indexzext: 285; CHECK: // %bb.0: 286; CHECK-NEXT: mov x8, #-1 // =0xffffffffffffffff 287; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 288; CHECK-NEXT: lsl x8, x8, x1 289; CHECK-NEXT: bic x0, x0, x8 290; CHECK-NEXT: ret 291 %conv = zext i8 %numlowbits to i64 292 %notmask = shl i64 -1, %conv 293 %mask = xor i64 %notmask, -1 294 %masked = and i64 %mask, %val 295 ret i64 %masked 296} 297 298define i64 @bzhi64_b2_load(ptr %w, i64 %numlowbits) nounwind { 299; CHECK-LABEL: bzhi64_b2_load: 300; CHECK: // %bb.0: 301; CHECK-NEXT: mov x8, #-1 // =0xffffffffffffffff 302; CHECK-NEXT: ldr x9, [x0] 303; CHECK-NEXT: lsl x8, x8, x1 304; CHECK-NEXT: bic x0, x9, x8 305; CHECK-NEXT: ret 306 %val = load i64, ptr %w 307 %notmask = shl i64 -1, %numlowbits 308 %mask = xor i64 %notmask, -1 309 %masked = and i64 %mask, %val 310 ret i64 %masked 311} 312 313define i64 @bzhi64_b3_load_indexzext(ptr %w, i8 zeroext %numlowbits) nounwind { 314; CHECK-LABEL: bzhi64_b3_load_indexzext: 315; CHECK: // %bb.0: 316; CHECK-NEXT: mov x8, #-1 // =0xffffffffffffffff 317; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 318; CHECK-NEXT: ldr x9, [x0] 319; CHECK-NEXT: lsl x8, x8, x1 320; CHECK-NEXT: bic x0, x9, x8 321; CHECK-NEXT: ret 322 %val = load i64, ptr %w 323 %conv = zext i8 %numlowbits to i64 324 %notmask = shl i64 -1, %conv 325 %mask = xor i64 %notmask, -1 326 %masked = and i64 %mask, %val 327 ret i64 %masked 328} 329 330define i64 @bzhi64_b4_commutative(i64 %val, i64 %numlowbits) nounwind { 331; CHECK-LABEL: bzhi64_b4_commutative: 332; CHECK: // %bb.0: 333; CHECK-NEXT: mov x8, #-1 // =0xffffffffffffffff 334; CHECK-NEXT: lsl x8, x8, x1 335; CHECK-NEXT: bic x0, x0, x8 336; CHECK-NEXT: ret 337 %notmask = shl i64 -1, %numlowbits 338 %mask = xor i64 %notmask, -1 339 %masked = and i64 %val, %mask ; swapped order 340 ret i64 %masked 341} 342 343; ---------------------------------------------------------------------------- ; 344; Pattern c. 32-bit 345; ---------------------------------------------------------------------------- ; 346 347define i32 @bzhi32_c0(i32 %val, i32 %numlowbits) nounwind { 348; CHECK-LABEL: bzhi32_c0: 349; CHECK: // %bb.0: 350; CHECK-NEXT: mov w8, #-1 // =0xffffffff 351; CHECK-NEXT: neg w9, w1 352; CHECK-NEXT: lsr w8, w8, w9 353; CHECK-NEXT: and w0, w8, w0 354; CHECK-NEXT: ret 355 %numhighbits = sub i32 32, %numlowbits 356 %mask = lshr i32 -1, %numhighbits 357 %masked = and i32 %mask, %val 358 ret i32 %masked 359} 360 361define i32 @bzhi32_c1_indexzext(i32 %val, i8 %numlowbits) nounwind { 362; CHECK-LABEL: bzhi32_c1_indexzext: 363; CHECK: // %bb.0: 364; CHECK-NEXT: mov w8, #32 // =0x20 365; CHECK-NEXT: mov w9, #-1 // =0xffffffff 366; CHECK-NEXT: sub w8, w8, w1 367; CHECK-NEXT: lsr w8, w9, w8 368; CHECK-NEXT: and w0, w8, w0 369; CHECK-NEXT: ret 370 %numhighbits = sub i8 32, %numlowbits 371 %sh_prom = zext i8 %numhighbits to i32 372 %mask = lshr i32 -1, %sh_prom 373 %masked = and i32 %mask, %val 374 ret i32 %masked 375} 376 377define i32 @bzhi32_c2_load(ptr %w, i32 %numlowbits) nounwind { 378; CHECK-LABEL: bzhi32_c2_load: 379; CHECK: // %bb.0: 380; CHECK-NEXT: mov w8, #-1 // =0xffffffff 381; CHECK-NEXT: neg w9, w1 382; CHECK-NEXT: ldr w10, [x0] 383; CHECK-NEXT: lsr w8, w8, w9 384; CHECK-NEXT: and w0, w8, w10 385; CHECK-NEXT: ret 386 %val = load i32, ptr %w 387 %numhighbits = sub i32 32, %numlowbits 388 %mask = lshr i32 -1, %numhighbits 389 %masked = and i32 %mask, %val 390 ret i32 %masked 391} 392 393define i32 @bzhi32_c3_load_indexzext(ptr %w, i8 %numlowbits) nounwind { 394; CHECK-LABEL: bzhi32_c3_load_indexzext: 395; CHECK: // %bb.0: 396; CHECK-NEXT: mov w8, #32 // =0x20 397; CHECK-NEXT: mov w9, #-1 // =0xffffffff 398; CHECK-NEXT: ldr w10, [x0] 399; CHECK-NEXT: sub w8, w8, w1 400; CHECK-NEXT: lsr w8, w9, w8 401; CHECK-NEXT: and w0, w8, w10 402; CHECK-NEXT: ret 403 %val = load i32, ptr %w 404 %numhighbits = sub i8 32, %numlowbits 405 %sh_prom = zext i8 %numhighbits to i32 406 %mask = lshr i32 -1, %sh_prom 407 %masked = and i32 %mask, %val 408 ret i32 %masked 409} 410 411define i32 @bzhi32_c4_commutative(i32 %val, i32 %numlowbits) nounwind { 412; CHECK-LABEL: bzhi32_c4_commutative: 413; CHECK: // %bb.0: 414; CHECK-NEXT: mov w8, #-1 // =0xffffffff 415; CHECK-NEXT: neg w9, w1 416; CHECK-NEXT: lsr w8, w8, w9 417; CHECK-NEXT: and w0, w0, w8 418; CHECK-NEXT: ret 419 %numhighbits = sub i32 32, %numlowbits 420 %mask = lshr i32 -1, %numhighbits 421 %masked = and i32 %val, %mask ; swapped order 422 ret i32 %masked 423} 424 425; 64-bit 426 427define i64 @bzhi64_c0(i64 %val, i64 %numlowbits) nounwind { 428; CHECK-LABEL: bzhi64_c0: 429; CHECK: // %bb.0: 430; CHECK-NEXT: mov x8, #-1 // =0xffffffffffffffff 431; CHECK-NEXT: neg x9, x1 432; CHECK-NEXT: lsr x8, x8, x9 433; CHECK-NEXT: and x0, x8, x0 434; CHECK-NEXT: ret 435 %numhighbits = sub i64 64, %numlowbits 436 %mask = lshr i64 -1, %numhighbits 437 %masked = and i64 %mask, %val 438 ret i64 %masked 439} 440 441define i64 @bzhi64_c1_indexzext(i64 %val, i8 %numlowbits) nounwind { 442; CHECK-LABEL: bzhi64_c1_indexzext: 443; CHECK: // %bb.0: 444; CHECK-NEXT: mov w8, #64 // =0x40 445; CHECK-NEXT: mov x9, #-1 // =0xffffffffffffffff 446; CHECK-NEXT: sub w8, w8, w1 447; CHECK-NEXT: lsr x8, x9, x8 448; CHECK-NEXT: and x0, x8, x0 449; CHECK-NEXT: ret 450 %numhighbits = sub i8 64, %numlowbits 451 %sh_prom = zext i8 %numhighbits to i64 452 %mask = lshr i64 -1, %sh_prom 453 %masked = and i64 %mask, %val 454 ret i64 %masked 455} 456 457define i64 @bzhi64_c2_load(ptr %w, i64 %numlowbits) nounwind { 458; CHECK-LABEL: bzhi64_c2_load: 459; CHECK: // %bb.0: 460; CHECK-NEXT: mov x8, #-1 // =0xffffffffffffffff 461; CHECK-NEXT: neg x9, x1 462; CHECK-NEXT: ldr x10, [x0] 463; CHECK-NEXT: lsr x8, x8, x9 464; CHECK-NEXT: and x0, x8, x10 465; CHECK-NEXT: ret 466 %val = load i64, ptr %w 467 %numhighbits = sub i64 64, %numlowbits 468 %mask = lshr i64 -1, %numhighbits 469 %masked = and i64 %mask, %val 470 ret i64 %masked 471} 472 473define i64 @bzhi64_c3_load_indexzext(ptr %w, i8 %numlowbits) nounwind { 474; CHECK-LABEL: bzhi64_c3_load_indexzext: 475; CHECK: // %bb.0: 476; CHECK-NEXT: mov w8, #64 // =0x40 477; CHECK-NEXT: mov x9, #-1 // =0xffffffffffffffff 478; CHECK-NEXT: ldr x10, [x0] 479; CHECK-NEXT: sub w8, w8, w1 480; CHECK-NEXT: lsr x8, x9, x8 481; CHECK-NEXT: and x0, x8, x10 482; CHECK-NEXT: ret 483 %val = load i64, ptr %w 484 %numhighbits = sub i8 64, %numlowbits 485 %sh_prom = zext i8 %numhighbits to i64 486 %mask = lshr i64 -1, %sh_prom 487 %masked = and i64 %mask, %val 488 ret i64 %masked 489} 490 491define i64 @bzhi64_c4_commutative(i64 %val, i64 %numlowbits) nounwind { 492; CHECK-LABEL: bzhi64_c4_commutative: 493; CHECK: // %bb.0: 494; CHECK-NEXT: mov x8, #-1 // =0xffffffffffffffff 495; CHECK-NEXT: neg x9, x1 496; CHECK-NEXT: lsr x8, x8, x9 497; CHECK-NEXT: and x0, x0, x8 498; CHECK-NEXT: ret 499 %numhighbits = sub i64 64, %numlowbits 500 %mask = lshr i64 -1, %numhighbits 501 %masked = and i64 %val, %mask ; swapped order 502 ret i64 %masked 503} 504 505; ---------------------------------------------------------------------------- ; 506; Pattern d. 32-bit. 507; ---------------------------------------------------------------------------- ; 508 509define i32 @bzhi32_d0(i32 %val, i32 %numlowbits) nounwind { 510; CHECK-LABEL: bzhi32_d0: 511; CHECK: // %bb.0: 512; CHECK-NEXT: neg w8, w1 513; CHECK-NEXT: lsl w9, w0, w8 514; CHECK-NEXT: lsr w0, w9, w8 515; CHECK-NEXT: ret 516 %numhighbits = sub i32 32, %numlowbits 517 %highbitscleared = shl i32 %val, %numhighbits 518 %masked = lshr i32 %highbitscleared, %numhighbits 519 ret i32 %masked 520} 521 522define i32 @bzhi32_d1_indexzext(i32 %val, i8 %numlowbits) nounwind { 523; CHECK-LABEL: bzhi32_d1_indexzext: 524; CHECK: // %bb.0: 525; CHECK-NEXT: mov w8, #32 // =0x20 526; CHECK-NEXT: sub w8, w8, w1 527; CHECK-NEXT: lsl w9, w0, w8 528; CHECK-NEXT: lsr w0, w9, w8 529; CHECK-NEXT: ret 530 %numhighbits = sub i8 32, %numlowbits 531 %sh_prom = zext i8 %numhighbits to i32 532 %highbitscleared = shl i32 %val, %sh_prom 533 %masked = lshr i32 %highbitscleared, %sh_prom 534 ret i32 %masked 535} 536 537define i32 @bzhi32_d2_load(ptr %w, i32 %numlowbits) nounwind { 538; CHECK-LABEL: bzhi32_d2_load: 539; CHECK: // %bb.0: 540; CHECK-NEXT: ldr w8, [x0] 541; CHECK-NEXT: neg w9, w1 542; CHECK-NEXT: lsl w8, w8, w9 543; CHECK-NEXT: lsr w0, w8, w9 544; CHECK-NEXT: ret 545 %val = load i32, ptr %w 546 %numhighbits = sub i32 32, %numlowbits 547 %highbitscleared = shl i32 %val, %numhighbits 548 %masked = lshr i32 %highbitscleared, %numhighbits 549 ret i32 %masked 550} 551 552define i32 @bzhi32_d3_load_indexzext(ptr %w, i8 %numlowbits) nounwind { 553; CHECK-LABEL: bzhi32_d3_load_indexzext: 554; CHECK: // %bb.0: 555; CHECK-NEXT: mov w8, #32 // =0x20 556; CHECK-NEXT: ldr w9, [x0] 557; CHECK-NEXT: sub w8, w8, w1 558; CHECK-NEXT: lsl w9, w9, w8 559; CHECK-NEXT: lsr w0, w9, w8 560; CHECK-NEXT: ret 561 %val = load i32, ptr %w 562 %numhighbits = sub i8 32, %numlowbits 563 %sh_prom = zext i8 %numhighbits to i32 564 %highbitscleared = shl i32 %val, %sh_prom 565 %masked = lshr i32 %highbitscleared, %sh_prom 566 ret i32 %masked 567} 568 569; 64-bit. 570 571define i64 @bzhi64_d0(i64 %val, i64 %numlowbits) nounwind { 572; CHECK-LABEL: bzhi64_d0: 573; CHECK: // %bb.0: 574; CHECK-NEXT: neg x8, x1 575; CHECK-NEXT: lsl x9, x0, x8 576; CHECK-NEXT: lsr x0, x9, x8 577; CHECK-NEXT: ret 578 %numhighbits = sub i64 64, %numlowbits 579 %highbitscleared = shl i64 %val, %numhighbits 580 %masked = lshr i64 %highbitscleared, %numhighbits 581 ret i64 %masked 582} 583 584define i64 @bzhi64_d1_indexzext(i64 %val, i8 %numlowbits) nounwind { 585; CHECK-LABEL: bzhi64_d1_indexzext: 586; CHECK: // %bb.0: 587; CHECK-NEXT: mov w8, #64 // =0x40 588; CHECK-NEXT: sub w8, w8, w1 589; CHECK-NEXT: lsl x9, x0, x8 590; CHECK-NEXT: lsr x0, x9, x8 591; CHECK-NEXT: ret 592 %numhighbits = sub i8 64, %numlowbits 593 %sh_prom = zext i8 %numhighbits to i64 594 %highbitscleared = shl i64 %val, %sh_prom 595 %masked = lshr i64 %highbitscleared, %sh_prom 596 ret i64 %masked 597} 598 599define i64 @bzhi64_d2_load(ptr %w, i64 %numlowbits) nounwind { 600; CHECK-LABEL: bzhi64_d2_load: 601; CHECK: // %bb.0: 602; CHECK-NEXT: ldr x8, [x0] 603; CHECK-NEXT: neg x9, x1 604; CHECK-NEXT: lsl x8, x8, x9 605; CHECK-NEXT: lsr x0, x8, x9 606; CHECK-NEXT: ret 607 %val = load i64, ptr %w 608 %numhighbits = sub i64 64, %numlowbits 609 %highbitscleared = shl i64 %val, %numhighbits 610 %masked = lshr i64 %highbitscleared, %numhighbits 611 ret i64 %masked 612} 613 614define i64 @bzhi64_d3_load_indexzext(ptr %w, i8 %numlowbits) nounwind { 615; CHECK-LABEL: bzhi64_d3_load_indexzext: 616; CHECK: // %bb.0: 617; CHECK-NEXT: mov w8, #64 // =0x40 618; CHECK-NEXT: ldr x9, [x0] 619; CHECK-NEXT: sub w8, w8, w1 620; CHECK-NEXT: lsl x9, x9, x8 621; CHECK-NEXT: lsr x0, x9, x8 622; CHECK-NEXT: ret 623 %val = load i64, ptr %w 624 %numhighbits = sub i8 64, %numlowbits 625 %sh_prom = zext i8 %numhighbits to i64 626 %highbitscleared = shl i64 %val, %sh_prom 627 %masked = lshr i64 %highbitscleared, %sh_prom 628 ret i64 %masked 629} 630 631; ---------------------------------------------------------------------------- ; 632; Constant mask 633; ---------------------------------------------------------------------------- ; 634 635; 32-bit 636 637define i32 @bzhi32_constant_mask32(i32 %val) nounwind { 638; CHECK-LABEL: bzhi32_constant_mask32: 639; CHECK: // %bb.0: 640; CHECK-NEXT: and w0, w0, #0x7fffffff 641; CHECK-NEXT: ret 642 %masked = and i32 %val, 2147483647 643 ret i32 %masked 644} 645 646define i32 @bzhi32_constant_mask32_load(ptr %val) nounwind { 647; CHECK-LABEL: bzhi32_constant_mask32_load: 648; CHECK: // %bb.0: 649; CHECK-NEXT: ldr w8, [x0] 650; CHECK-NEXT: and w0, w8, #0x7fffffff 651; CHECK-NEXT: ret 652 %val1 = load i32, ptr %val 653 %masked = and i32 %val1, 2147483647 654 ret i32 %masked 655} 656 657define i32 @bzhi32_constant_mask16(i32 %val) nounwind { 658; CHECK-LABEL: bzhi32_constant_mask16: 659; CHECK: // %bb.0: 660; CHECK-NEXT: and w0, w0, #0x7fff 661; CHECK-NEXT: ret 662 %masked = and i32 %val, 32767 663 ret i32 %masked 664} 665 666define i32 @bzhi32_constant_mask16_load(ptr %val) nounwind { 667; CHECK-LABEL: bzhi32_constant_mask16_load: 668; CHECK: // %bb.0: 669; CHECK-NEXT: ldr w8, [x0] 670; CHECK-NEXT: and w0, w8, #0x7fff 671; CHECK-NEXT: ret 672 %val1 = load i32, ptr %val 673 %masked = and i32 %val1, 32767 674 ret i32 %masked 675} 676 677define i32 @bzhi32_constant_mask8(i32 %val) nounwind { 678; CHECK-LABEL: bzhi32_constant_mask8: 679; CHECK: // %bb.0: 680; CHECK-NEXT: and w0, w0, #0x7f 681; CHECK-NEXT: ret 682 %masked = and i32 %val, 127 683 ret i32 %masked 684} 685 686define i32 @bzhi32_constant_mask8_load(ptr %val) nounwind { 687; CHECK-LABEL: bzhi32_constant_mask8_load: 688; CHECK: // %bb.0: 689; CHECK-NEXT: ldr w8, [x0] 690; CHECK-NEXT: and w0, w8, #0x7f 691; CHECK-NEXT: ret 692 %val1 = load i32, ptr %val 693 %masked = and i32 %val1, 127 694 ret i32 %masked 695} 696 697; 64-bit 698 699define i64 @bzhi64_constant_mask64(i64 %val) nounwind { 700; CHECK-LABEL: bzhi64_constant_mask64: 701; CHECK: // %bb.0: 702; CHECK-NEXT: and x0, x0, #0x3fffffffffffffff 703; CHECK-NEXT: ret 704 %masked = and i64 %val, 4611686018427387903 705 ret i64 %masked 706} 707 708define i64 @bzhi64_constant_mask64_load(ptr %val) nounwind { 709; CHECK-LABEL: bzhi64_constant_mask64_load: 710; CHECK: // %bb.0: 711; CHECK-NEXT: ldr x8, [x0] 712; CHECK-NEXT: and x0, x8, #0x3fffffffffffffff 713; CHECK-NEXT: ret 714 %val1 = load i64, ptr %val 715 %masked = and i64 %val1, 4611686018427387903 716 ret i64 %masked 717} 718 719define i64 @bzhi64_constant_mask32(i64 %val) nounwind { 720; CHECK-LABEL: bzhi64_constant_mask32: 721; CHECK: // %bb.0: 722; CHECK-NEXT: and x0, x0, #0x7fffffff 723; CHECK-NEXT: ret 724 %masked = and i64 %val, 2147483647 725 ret i64 %masked 726} 727 728define i64 @bzhi64_constant_mask32_load(ptr %val) nounwind { 729; CHECK-LABEL: bzhi64_constant_mask32_load: 730; CHECK: // %bb.0: 731; CHECK-NEXT: ldr x8, [x0] 732; CHECK-NEXT: and x0, x8, #0x7fffffff 733; CHECK-NEXT: ret 734 %val1 = load i64, ptr %val 735 %masked = and i64 %val1, 2147483647 736 ret i64 %masked 737} 738 739define i64 @bzhi64_constant_mask16(i64 %val) nounwind { 740; CHECK-LABEL: bzhi64_constant_mask16: 741; CHECK: // %bb.0: 742; CHECK-NEXT: and x0, x0, #0x7fff 743; CHECK-NEXT: ret 744 %masked = and i64 %val, 32767 745 ret i64 %masked 746} 747 748define i64 @bzhi64_constant_mask16_load(ptr %val) nounwind { 749; CHECK-LABEL: bzhi64_constant_mask16_load: 750; CHECK: // %bb.0: 751; CHECK-NEXT: ldr x8, [x0] 752; CHECK-NEXT: and x0, x8, #0x7fff 753; CHECK-NEXT: ret 754 %val1 = load i64, ptr %val 755 %masked = and i64 %val1, 32767 756 ret i64 %masked 757} 758 759define i64 @bzhi64_constant_mask8(i64 %val) nounwind { 760; CHECK-LABEL: bzhi64_constant_mask8: 761; CHECK: // %bb.0: 762; CHECK-NEXT: and x0, x0, #0x7f 763; CHECK-NEXT: ret 764 %masked = and i64 %val, 127 765 ret i64 %masked 766} 767 768define i64 @bzhi64_constant_mask8_load(ptr %val) nounwind { 769; CHECK-LABEL: bzhi64_constant_mask8_load: 770; CHECK: // %bb.0: 771; CHECK-NEXT: ldr x8, [x0] 772; CHECK-NEXT: and x0, x8, #0x7f 773; CHECK-NEXT: ret 774 %val1 = load i64, ptr %val 775 %masked = and i64 %val1, 127 776 ret i64 %masked 777} 778