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