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-bits.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 >> start) & (1 << nbits) - 1 12; b) (x >> start) & ~(-1 << nbits) 13; c) (x >> start) & (-1 >> (32 - y)) 14; d) (x >> start) << (32 - y) >> (32 - y) 15; are equivalent. 16 17; ---------------------------------------------------------------------------- ; 18; Pattern a. 32-bit 19; ---------------------------------------------------------------------------- ; 20 21define i32 @bextr32_a0(i32 %val, i32 %numskipbits, i32 %numlowbits) nounwind { 22; CHECK-LABEL: bextr32_a0: 23; CHECK: // %bb.0: 24; CHECK-NEXT: orr w9, wzr, #0x1 25; CHECK-NEXT: lsl w9, w9, w2 26; CHECK-NEXT: lsr w8, w0, w1 27; CHECK-NEXT: sub w9, w9, #1 // =1 28; CHECK-NEXT: and w0, w9, w8 29; CHECK-NEXT: ret 30 %shifted = lshr i32 %val, %numskipbits 31 %onebit = shl i32 1, %numlowbits 32 %mask = add nsw i32 %onebit, -1 33 %masked = and i32 %mask, %shifted 34 ret i32 %masked 35} 36 37define i32 @bextr32_a1_indexzext(i32 %val, i8 zeroext %numskipbits, i8 zeroext %numlowbits) nounwind { 38; CHECK-LABEL: bextr32_a1_indexzext: 39; CHECK: // %bb.0: 40; CHECK-NEXT: orr w9, wzr, #0x1 41; CHECK-NEXT: lsl w9, w9, w2 42; CHECK-NEXT: lsr w8, w0, w1 43; CHECK-NEXT: sub w9, w9, #1 // =1 44; CHECK-NEXT: and w0, w9, w8 45; CHECK-NEXT: ret 46 %skip = zext i8 %numskipbits to i32 47 %shifted = lshr i32 %val, %skip 48 %conv = zext i8 %numlowbits to i32 49 %onebit = shl i32 1, %conv 50 %mask = add nsw i32 %onebit, -1 51 %masked = and i32 %mask, %shifted 52 ret i32 %masked 53} 54 55define i32 @bextr32_a2_load(i32* %w, i32 %numskipbits, i32 %numlowbits) nounwind { 56; CHECK-LABEL: bextr32_a2_load: 57; CHECK: // %bb.0: 58; CHECK-NEXT: ldr w8, [x0] 59; CHECK-NEXT: orr w9, wzr, #0x1 60; CHECK-NEXT: lsl w9, w9, w2 61; CHECK-NEXT: sub w9, w9, #1 // =1 62; CHECK-NEXT: lsr w8, w8, w1 63; CHECK-NEXT: and w0, w9, w8 64; CHECK-NEXT: ret 65 %val = load i32, i32* %w 66 %shifted = lshr i32 %val, %numskipbits 67 %onebit = shl i32 1, %numlowbits 68 %mask = add nsw i32 %onebit, -1 69 %masked = and i32 %mask, %shifted 70 ret i32 %masked 71} 72 73define i32 @bextr32_a3_load_indexzext(i32* %w, i8 zeroext %numskipbits, i8 zeroext %numlowbits) nounwind { 74; CHECK-LABEL: bextr32_a3_load_indexzext: 75; CHECK: // %bb.0: 76; CHECK-NEXT: ldr w8, [x0] 77; CHECK-NEXT: orr w9, wzr, #0x1 78; CHECK-NEXT: lsl w9, w9, w2 79; CHECK-NEXT: sub w9, w9, #1 // =1 80; CHECK-NEXT: lsr w8, w8, w1 81; CHECK-NEXT: and w0, w9, w8 82; CHECK-NEXT: ret 83 %val = load i32, i32* %w 84 %skip = zext i8 %numskipbits to i32 85 %shifted = lshr i32 %val, %skip 86 %conv = zext i8 %numlowbits to i32 87 %onebit = shl i32 1, %conv 88 %mask = add nsw i32 %onebit, -1 89 %masked = and i32 %mask, %shifted 90 ret i32 %masked 91} 92 93define i32 @bextr32_a4_commutative(i32 %val, i32 %numskipbits, i32 %numlowbits) nounwind { 94; CHECK-LABEL: bextr32_a4_commutative: 95; CHECK: // %bb.0: 96; CHECK-NEXT: orr w9, wzr, #0x1 97; CHECK-NEXT: lsl w9, w9, w2 98; CHECK-NEXT: lsr w8, w0, w1 99; CHECK-NEXT: sub w9, w9, #1 // =1 100; CHECK-NEXT: and w0, w8, w9 101; CHECK-NEXT: ret 102 %shifted = lshr i32 %val, %numskipbits 103 %onebit = shl i32 1, %numlowbits 104 %mask = add nsw i32 %onebit, -1 105 %masked = and i32 %shifted, %mask ; swapped order 106 ret i32 %masked 107} 108 109; 64-bit 110 111define i64 @bextr64_a0(i64 %val, i64 %numskipbits, i64 %numlowbits) nounwind { 112; CHECK-LABEL: bextr64_a0: 113; CHECK: // %bb.0: 114; CHECK-NEXT: orr w9, wzr, #0x1 115; CHECK-NEXT: lsl x9, x9, x2 116; CHECK-NEXT: lsr x8, x0, x1 117; CHECK-NEXT: sub x9, x9, #1 // =1 118; CHECK-NEXT: and x0, x9, x8 119; CHECK-NEXT: ret 120 %shifted = lshr i64 %val, %numskipbits 121 %onebit = shl i64 1, %numlowbits 122 %mask = add nsw i64 %onebit, -1 123 %masked = and i64 %mask, %shifted 124 ret i64 %masked 125} 126 127define i64 @bextr64_a1_indexzext(i64 %val, i8 zeroext %numskipbits, i8 zeroext %numlowbits) nounwind { 128; CHECK-LABEL: bextr64_a1_indexzext: 129; CHECK: // %bb.0: 130; CHECK-NEXT: orr w9, wzr, #0x1 131; CHECK-NEXT: // kill: def $w2 killed $w2 def $x2 132; CHECK-NEXT: lsl x9, x9, x2 133; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 134; CHECK-NEXT: lsr x8, x0, x1 135; CHECK-NEXT: sub x9, x9, #1 // =1 136; CHECK-NEXT: and x0, x9, x8 137; CHECK-NEXT: ret 138 %skip = zext i8 %numskipbits to i64 139 %shifted = lshr i64 %val, %skip 140 %conv = zext i8 %numlowbits to i64 141 %onebit = shl i64 1, %conv 142 %mask = add nsw i64 %onebit, -1 143 %masked = and i64 %mask, %shifted 144 ret i64 %masked 145} 146 147define i64 @bextr64_a2_load(i64* %w, i64 %numskipbits, i64 %numlowbits) nounwind { 148; CHECK-LABEL: bextr64_a2_load: 149; CHECK: // %bb.0: 150; CHECK-NEXT: ldr x8, [x0] 151; CHECK-NEXT: orr w9, wzr, #0x1 152; CHECK-NEXT: lsl x9, x9, x2 153; CHECK-NEXT: sub x9, x9, #1 // =1 154; CHECK-NEXT: lsr x8, x8, x1 155; CHECK-NEXT: and x0, x9, x8 156; CHECK-NEXT: ret 157 %val = load i64, i64* %w 158 %shifted = lshr i64 %val, %numskipbits 159 %onebit = shl i64 1, %numlowbits 160 %mask = add nsw i64 %onebit, -1 161 %masked = and i64 %mask, %shifted 162 ret i64 %masked 163} 164 165define i64 @bextr64_a3_load_indexzext(i64* %w, i8 zeroext %numskipbits, i8 zeroext %numlowbits) nounwind { 166; CHECK-LABEL: bextr64_a3_load_indexzext: 167; CHECK: // %bb.0: 168; CHECK-NEXT: ldr x8, [x0] 169; CHECK-NEXT: orr w9, wzr, #0x1 170; CHECK-NEXT: // kill: def $w2 killed $w2 def $x2 171; CHECK-NEXT: lsl x9, x9, x2 172; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 173; CHECK-NEXT: sub x9, x9, #1 // =1 174; CHECK-NEXT: lsr x8, x8, x1 175; CHECK-NEXT: and x0, x9, x8 176; CHECK-NEXT: ret 177 %val = load i64, i64* %w 178 %skip = zext i8 %numskipbits to i64 179 %shifted = lshr i64 %val, %skip 180 %conv = zext i8 %numlowbits to i64 181 %onebit = shl i64 1, %conv 182 %mask = add nsw i64 %onebit, -1 183 %masked = and i64 %mask, %shifted 184 ret i64 %masked 185} 186 187define i64 @bextr64_a4_commutative(i64 %val, i64 %numskipbits, i64 %numlowbits) nounwind { 188; CHECK-LABEL: bextr64_a4_commutative: 189; CHECK: // %bb.0: 190; CHECK-NEXT: orr w9, wzr, #0x1 191; CHECK-NEXT: lsl x9, x9, x2 192; CHECK-NEXT: lsr x8, x0, x1 193; CHECK-NEXT: sub x9, x9, #1 // =1 194; CHECK-NEXT: and x0, x8, x9 195; CHECK-NEXT: ret 196 %shifted = lshr i64 %val, %numskipbits 197 %onebit = shl i64 1, %numlowbits 198 %mask = add nsw i64 %onebit, -1 199 %masked = and i64 %shifted, %mask ; swapped order 200 ret i64 %masked 201} 202 203; ---------------------------------------------------------------------------- ; 204; Pattern b. 32-bit 205; ---------------------------------------------------------------------------- ; 206 207define i32 @bextr32_b0(i32 %val, i32 %numskipbits, i32 %numlowbits) nounwind { 208; CHECK-LABEL: bextr32_b0: 209; CHECK: // %bb.0: 210; CHECK-NEXT: mov w9, #-1 211; CHECK-NEXT: lsr w8, w0, w1 212; CHECK-NEXT: lsl w9, w9, w2 213; CHECK-NEXT: bic w0, w8, w9 214; CHECK-NEXT: ret 215 %shifted = lshr i32 %val, %numskipbits 216 %notmask = shl i32 -1, %numlowbits 217 %mask = xor i32 %notmask, -1 218 %masked = and i32 %mask, %shifted 219 ret i32 %masked 220} 221 222define i32 @bextr32_b1_indexzext(i32 %val, i8 zeroext %numskipbits, i8 zeroext %numlowbits) nounwind { 223; CHECK-LABEL: bextr32_b1_indexzext: 224; CHECK: // %bb.0: 225; CHECK-NEXT: mov w9, #-1 226; CHECK-NEXT: lsr w8, w0, w1 227; CHECK-NEXT: lsl w9, w9, w2 228; CHECK-NEXT: bic w0, w8, w9 229; CHECK-NEXT: ret 230 %skip = zext i8 %numskipbits to i32 231 %shifted = lshr i32 %val, %skip 232 %conv = zext i8 %numlowbits to i32 233 %notmask = shl i32 -1, %conv 234 %mask = xor i32 %notmask, -1 235 %masked = and i32 %mask, %shifted 236 ret i32 %masked 237} 238 239define i32 @bextr32_b2_load(i32* %w, i32 %numskipbits, i32 %numlowbits) nounwind { 240; CHECK-LABEL: bextr32_b2_load: 241; CHECK: // %bb.0: 242; CHECK-NEXT: ldr w8, [x0] 243; CHECK-NEXT: mov w9, #-1 244; CHECK-NEXT: lsl w9, w9, w2 245; CHECK-NEXT: lsr w8, w8, w1 246; CHECK-NEXT: bic w0, w8, w9 247; CHECK-NEXT: ret 248 %val = load i32, i32* %w 249 %shifted = lshr i32 %val, %numskipbits 250 %notmask = shl i32 -1, %numlowbits 251 %mask = xor i32 %notmask, -1 252 %masked = and i32 %mask, %shifted 253 ret i32 %masked 254} 255 256define i32 @bextr32_b3_load_indexzext(i32* %w, i8 zeroext %numskipbits, i8 zeroext %numlowbits) nounwind { 257; CHECK-LABEL: bextr32_b3_load_indexzext: 258; CHECK: // %bb.0: 259; CHECK-NEXT: ldr w8, [x0] 260; CHECK-NEXT: mov w9, #-1 261; CHECK-NEXT: lsl w9, w9, w2 262; CHECK-NEXT: lsr w8, w8, w1 263; CHECK-NEXT: bic w0, w8, w9 264; CHECK-NEXT: ret 265 %val = load i32, i32* %w 266 %skip = zext i8 %numskipbits to i32 267 %shifted = lshr i32 %val, %skip 268 %conv = zext i8 %numlowbits to i32 269 %notmask = shl i32 -1, %conv 270 %mask = xor i32 %notmask, -1 271 %masked = and i32 %mask, %shifted 272 ret i32 %masked 273} 274 275define i32 @bextr32_b4_commutative(i32 %val, i32 %numskipbits, i32 %numlowbits) nounwind { 276; CHECK-LABEL: bextr32_b4_commutative: 277; CHECK: // %bb.0: 278; CHECK-NEXT: mov w9, #-1 279; CHECK-NEXT: lsr w8, w0, w1 280; CHECK-NEXT: lsl w9, w9, w2 281; CHECK-NEXT: bic w0, w8, w9 282; CHECK-NEXT: ret 283 %shifted = lshr i32 %val, %numskipbits 284 %notmask = shl i32 -1, %numlowbits 285 %mask = xor i32 %notmask, -1 286 %masked = and i32 %shifted, %mask ; swapped order 287 ret i32 %masked 288} 289 290; 64-bit 291 292define i64 @bextr64_b0(i64 %val, i64 %numskipbits, i64 %numlowbits) nounwind { 293; CHECK-LABEL: bextr64_b0: 294; CHECK: // %bb.0: 295; CHECK-NEXT: mov x9, #-1 296; CHECK-NEXT: lsr x8, x0, x1 297; CHECK-NEXT: lsl x9, x9, x2 298; CHECK-NEXT: bic x0, x8, x9 299; CHECK-NEXT: ret 300 %shifted = lshr i64 %val, %numskipbits 301 %notmask = shl i64 -1, %numlowbits 302 %mask = xor i64 %notmask, -1 303 %masked = and i64 %mask, %shifted 304 ret i64 %masked 305} 306 307define i64 @bextr64_b1_indexzext(i64 %val, i8 zeroext %numskipbits, i8 zeroext %numlowbits) nounwind { 308; CHECK-LABEL: bextr64_b1_indexzext: 309; CHECK: // %bb.0: 310; CHECK-NEXT: mov x9, #-1 311; CHECK-NEXT: // kill: def $w2 killed $w2 def $x2 312; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 313; CHECK-NEXT: lsr x8, x0, x1 314; CHECK-NEXT: lsl x9, x9, x2 315; CHECK-NEXT: bic x0, x8, x9 316; CHECK-NEXT: ret 317 %skip = zext i8 %numskipbits to i64 318 %shifted = lshr i64 %val, %skip 319 %conv = zext i8 %numlowbits to i64 320 %notmask = shl i64 -1, %conv 321 %mask = xor i64 %notmask, -1 322 %masked = and i64 %mask, %shifted 323 ret i64 %masked 324} 325 326define i64 @bextr64_b2_load(i64* %w, i64 %numskipbits, i64 %numlowbits) nounwind { 327; CHECK-LABEL: bextr64_b2_load: 328; CHECK: // %bb.0: 329; CHECK-NEXT: ldr x8, [x0] 330; CHECK-NEXT: mov x9, #-1 331; CHECK-NEXT: lsl x9, x9, x2 332; CHECK-NEXT: lsr x8, x8, x1 333; CHECK-NEXT: bic x0, x8, x9 334; CHECK-NEXT: ret 335 %val = load i64, i64* %w 336 %shifted = lshr i64 %val, %numskipbits 337 %notmask = shl i64 -1, %numlowbits 338 %mask = xor i64 %notmask, -1 339 %masked = and i64 %mask, %shifted 340 ret i64 %masked 341} 342 343define i64 @bextr64_b3_load_indexzext(i64* %w, i8 zeroext %numskipbits, i8 zeroext %numlowbits) nounwind { 344; CHECK-LABEL: bextr64_b3_load_indexzext: 345; CHECK: // %bb.0: 346; CHECK-NEXT: ldr x8, [x0] 347; CHECK-NEXT: mov x9, #-1 348; CHECK-NEXT: // kill: def $w2 killed $w2 def $x2 349; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 350; CHECK-NEXT: lsl x9, x9, x2 351; CHECK-NEXT: lsr x8, x8, x1 352; CHECK-NEXT: bic x0, x8, x9 353; CHECK-NEXT: ret 354 %val = load i64, i64* %w 355 %skip = zext i8 %numskipbits to i64 356 %shifted = lshr i64 %val, %skip 357 %conv = zext i8 %numlowbits to i64 358 %notmask = shl i64 -1, %conv 359 %mask = xor i64 %notmask, -1 360 %masked = and i64 %mask, %shifted 361 ret i64 %masked 362} 363 364define i64 @bextr64_b4_commutative(i64 %val, i64 %numskipbits, i64 %numlowbits) nounwind { 365; CHECK-LABEL: bextr64_b4_commutative: 366; CHECK: // %bb.0: 367; CHECK-NEXT: mov x9, #-1 368; CHECK-NEXT: lsr x8, x0, x1 369; CHECK-NEXT: lsl x9, x9, x2 370; CHECK-NEXT: bic x0, x8, x9 371; CHECK-NEXT: ret 372 %shifted = lshr i64 %val, %numskipbits 373 %notmask = shl i64 -1, %numlowbits 374 %mask = xor i64 %notmask, -1 375 %masked = and i64 %shifted, %mask ; swapped order 376 ret i64 %masked 377} 378 379; ---------------------------------------------------------------------------- ; 380; Pattern c. 32-bit 381; ---------------------------------------------------------------------------- ; 382 383define i32 @bextr32_c0(i32 %val, i32 %numskipbits, i32 %numlowbits) nounwind { 384; CHECK-LABEL: bextr32_c0: 385; CHECK: // %bb.0: 386; CHECK-NEXT: neg w9, w2 387; CHECK-NEXT: mov w10, #-1 388; CHECK-NEXT: lsr w8, w0, w1 389; CHECK-NEXT: lsr w9, w10, w9 390; CHECK-NEXT: and w0, w9, w8 391; CHECK-NEXT: ret 392 %shifted = lshr i32 %val, %numskipbits 393 %numhighbits = sub i32 32, %numlowbits 394 %mask = lshr i32 -1, %numhighbits 395 %masked = and i32 %mask, %shifted 396 ret i32 %masked 397} 398 399define i32 @bextr32_c1_indexzext(i32 %val, i8 %numskipbits, i8 %numlowbits) nounwind { 400; CHECK-LABEL: bextr32_c1_indexzext: 401; CHECK: // %bb.0: 402; CHECK-NEXT: orr w9, wzr, #0x20 403; CHECK-NEXT: sub w9, w9, w2 404; CHECK-NEXT: mov w10, #-1 405; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 406; CHECK-NEXT: lsr w8, w0, w1 407; CHECK-NEXT: lsr w9, w10, w9 408; CHECK-NEXT: and w0, w9, w8 409; CHECK-NEXT: ret 410 %skip = zext i8 %numskipbits to i32 411 %shifted = lshr i32 %val, %skip 412 %numhighbits = sub i8 32, %numlowbits 413 %sh_prom = zext i8 %numhighbits to i32 414 %mask = lshr i32 -1, %sh_prom 415 %masked = and i32 %mask, %shifted 416 ret i32 %masked 417} 418 419define i32 @bextr32_c2_load(i32* %w, i32 %numskipbits, i32 %numlowbits) nounwind { 420; CHECK-LABEL: bextr32_c2_load: 421; CHECK: // %bb.0: 422; CHECK-NEXT: ldr w8, [x0] 423; CHECK-NEXT: neg w9, w2 424; CHECK-NEXT: mov w10, #-1 425; CHECK-NEXT: lsr w9, w10, w9 426; CHECK-NEXT: lsr w8, w8, w1 427; CHECK-NEXT: and w0, w9, w8 428; CHECK-NEXT: ret 429 %val = load i32, i32* %w 430 %shifted = lshr i32 %val, %numskipbits 431 %numhighbits = sub i32 32, %numlowbits 432 %mask = lshr i32 -1, %numhighbits 433 %masked = and i32 %mask, %shifted 434 ret i32 %masked 435} 436 437define i32 @bextr32_c3_load_indexzext(i32* %w, i8 %numskipbits, i8 %numlowbits) nounwind { 438; CHECK-LABEL: bextr32_c3_load_indexzext: 439; CHECK: // %bb.0: 440; CHECK-NEXT: ldr w8, [x0] 441; CHECK-NEXT: orr w9, wzr, #0x20 442; CHECK-NEXT: mov w10, #-1 443; CHECK-NEXT: sub w9, w9, w2 444; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 445; CHECK-NEXT: lsr w8, w8, w1 446; CHECK-NEXT: lsr w9, w10, w9 447; CHECK-NEXT: and w0, w9, w8 448; CHECK-NEXT: ret 449 %val = load i32, i32* %w 450 %skip = zext i8 %numskipbits to i32 451 %shifted = lshr i32 %val, %skip 452 %numhighbits = sub i8 32, %numlowbits 453 %sh_prom = zext i8 %numhighbits to i32 454 %mask = lshr i32 -1, %sh_prom 455 %masked = and i32 %mask, %shifted 456 ret i32 %masked 457} 458 459define i32 @bextr32_c4_commutative(i32 %val, i32 %numskipbits, i32 %numlowbits) nounwind { 460; CHECK-LABEL: bextr32_c4_commutative: 461; CHECK: // %bb.0: 462; CHECK-NEXT: neg w9, w2 463; CHECK-NEXT: mov w10, #-1 464; CHECK-NEXT: lsr w8, w0, w1 465; CHECK-NEXT: lsr w9, w10, w9 466; CHECK-NEXT: and w0, w8, w9 467; CHECK-NEXT: ret 468 %shifted = lshr i32 %val, %numskipbits 469 %numhighbits = sub i32 32, %numlowbits 470 %mask = lshr i32 -1, %numhighbits 471 %masked = and i32 %shifted, %mask ; swapped order 472 ret i32 %masked 473} 474 475; 64-bit 476 477define i64 @bextr64_c0(i64 %val, i64 %numskipbits, i64 %numlowbits) nounwind { 478; CHECK-LABEL: bextr64_c0: 479; CHECK: // %bb.0: 480; CHECK-NEXT: neg x9, x2 481; CHECK-NEXT: mov x10, #-1 482; CHECK-NEXT: lsr x8, x0, x1 483; CHECK-NEXT: lsr x9, x10, x9 484; CHECK-NEXT: and x0, x9, x8 485; CHECK-NEXT: ret 486 %shifted = lshr i64 %val, %numskipbits 487 %numhighbits = sub i64 64, %numlowbits 488 %mask = lshr i64 -1, %numhighbits 489 %masked = and i64 %mask, %shifted 490 ret i64 %masked 491} 492 493define i64 @bextr64_c1_indexzext(i64 %val, i8 %numskipbits, i8 %numlowbits) nounwind { 494; CHECK-LABEL: bextr64_c1_indexzext: 495; CHECK: // %bb.0: 496; CHECK-NEXT: orr w9, wzr, #0x40 497; CHECK-NEXT: sub w9, w9, w2 498; CHECK-NEXT: mov x10, #-1 499; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 500; CHECK-NEXT: lsr x8, x0, x1 501; CHECK-NEXT: lsr x9, x10, x9 502; CHECK-NEXT: and x0, x9, x8 503; CHECK-NEXT: ret 504 %skip = zext i8 %numskipbits to i64 505 %shifted = lshr i64 %val, %skip 506 %numhighbits = sub i8 64, %numlowbits 507 %sh_prom = zext i8 %numhighbits to i64 508 %mask = lshr i64 -1, %sh_prom 509 %masked = and i64 %mask, %shifted 510 ret i64 %masked 511} 512 513define i64 @bextr64_c2_load(i64* %w, i64 %numskipbits, i64 %numlowbits) nounwind { 514; CHECK-LABEL: bextr64_c2_load: 515; CHECK: // %bb.0: 516; CHECK-NEXT: ldr x8, [x0] 517; CHECK-NEXT: neg x9, x2 518; CHECK-NEXT: mov x10, #-1 519; CHECK-NEXT: lsr x9, x10, x9 520; CHECK-NEXT: lsr x8, x8, x1 521; CHECK-NEXT: and x0, x9, x8 522; CHECK-NEXT: ret 523 %val = load i64, i64* %w 524 %shifted = lshr i64 %val, %numskipbits 525 %numhighbits = sub i64 64, %numlowbits 526 %mask = lshr i64 -1, %numhighbits 527 %masked = and i64 %mask, %shifted 528 ret i64 %masked 529} 530 531define i64 @bextr64_c3_load_indexzext(i64* %w, i8 %numskipbits, i8 %numlowbits) nounwind { 532; CHECK-LABEL: bextr64_c3_load_indexzext: 533; CHECK: // %bb.0: 534; CHECK-NEXT: ldr x8, [x0] 535; CHECK-NEXT: orr w9, wzr, #0x40 536; CHECK-NEXT: mov x10, #-1 537; CHECK-NEXT: sub w9, w9, w2 538; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 539; CHECK-NEXT: lsr x8, x8, x1 540; CHECK-NEXT: lsr x9, x10, x9 541; CHECK-NEXT: and x0, x9, x8 542; CHECK-NEXT: ret 543 %val = load i64, i64* %w 544 %skip = zext i8 %numskipbits to i64 545 %shifted = lshr i64 %val, %skip 546 %numhighbits = sub i8 64, %numlowbits 547 %sh_prom = zext i8 %numhighbits to i64 548 %mask = lshr i64 -1, %sh_prom 549 %masked = and i64 %mask, %shifted 550 ret i64 %masked 551} 552 553define i64 @bextr64_c4_commutative(i64 %val, i64 %numskipbits, i64 %numlowbits) nounwind { 554; CHECK-LABEL: bextr64_c4_commutative: 555; CHECK: // %bb.0: 556; CHECK-NEXT: neg x9, x2 557; CHECK-NEXT: mov x10, #-1 558; CHECK-NEXT: lsr x8, x0, x1 559; CHECK-NEXT: lsr x9, x10, x9 560; CHECK-NEXT: and x0, x8, x9 561; CHECK-NEXT: ret 562 %shifted = lshr i64 %val, %numskipbits 563 %numhighbits = sub i64 64, %numlowbits 564 %mask = lshr i64 -1, %numhighbits 565 %masked = and i64 %shifted, %mask ; swapped order 566 ret i64 %masked 567} 568 569; ---------------------------------------------------------------------------- ; 570; Pattern d. 32-bit. 571; ---------------------------------------------------------------------------- ; 572 573define i32 @bextr32_d0(i32 %val, i32 %numskipbits, i32 %numlowbits) nounwind { 574; CHECK-LABEL: bextr32_d0: 575; CHECK: // %bb.0: 576; CHECK-NEXT: lsr w8, w0, w1 577; CHECK-NEXT: neg w9, w2 578; CHECK-NEXT: lsl w8, w8, w9 579; CHECK-NEXT: lsr w0, w8, w9 580; CHECK-NEXT: ret 581 %shifted = lshr i32 %val, %numskipbits 582 %numhighbits = sub i32 32, %numlowbits 583 %highbitscleared = shl i32 %shifted, %numhighbits 584 %masked = lshr i32 %highbitscleared, %numhighbits 585 ret i32 %masked 586} 587 588define i32 @bextr32_d1_indexzext(i32 %val, i8 %numskipbits, i8 %numlowbits) nounwind { 589; CHECK-LABEL: bextr32_d1_indexzext: 590; CHECK: // %bb.0: 591; CHECK-NEXT: orr w9, wzr, #0x20 592; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 593; CHECK-NEXT: lsr w8, w0, w1 594; CHECK-NEXT: sub w9, w9, w2 595; CHECK-NEXT: lsl w8, w8, w9 596; CHECK-NEXT: lsr w0, w8, w9 597; CHECK-NEXT: ret 598 %skip = zext i8 %numskipbits to i32 599 %shifted = lshr i32 %val, %skip 600 %numhighbits = sub i8 32, %numlowbits 601 %sh_prom = zext i8 %numhighbits to i32 602 %highbitscleared = shl i32 %shifted, %sh_prom 603 %masked = lshr i32 %highbitscleared, %sh_prom 604 ret i32 %masked 605} 606 607define i32 @bextr32_d2_load(i32* %w, i32 %numskipbits, i32 %numlowbits) nounwind { 608; CHECK-LABEL: bextr32_d2_load: 609; CHECK: // %bb.0: 610; CHECK-NEXT: ldr w8, [x0] 611; CHECK-NEXT: neg w9, w2 612; CHECK-NEXT: lsr w8, w8, w1 613; CHECK-NEXT: lsl w8, w8, w9 614; CHECK-NEXT: lsr w0, w8, w9 615; CHECK-NEXT: ret 616 %val = load i32, i32* %w 617 %shifted = lshr i32 %val, %numskipbits 618 %numhighbits = sub i32 32, %numlowbits 619 %highbitscleared = shl i32 %shifted, %numhighbits 620 %masked = lshr i32 %highbitscleared, %numhighbits 621 ret i32 %masked 622} 623 624define i32 @bextr32_d3_load_indexzext(i32* %w, i8 %numskipbits, i8 %numlowbits) nounwind { 625; CHECK-LABEL: bextr32_d3_load_indexzext: 626; CHECK: // %bb.0: 627; CHECK-NEXT: ldr w8, [x0] 628; CHECK-NEXT: orr w9, wzr, #0x20 629; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 630; CHECK-NEXT: sub w9, w9, w2 631; CHECK-NEXT: lsr w8, w8, w1 632; CHECK-NEXT: lsl w8, w8, w9 633; CHECK-NEXT: lsr w0, w8, w9 634; CHECK-NEXT: ret 635 %val = load i32, i32* %w 636 %skip = zext i8 %numskipbits to i32 637 %shifted = lshr i32 %val, %skip 638 %numhighbits = sub i8 32, %numlowbits 639 %sh_prom = zext i8 %numhighbits to i32 640 %highbitscleared = shl i32 %shifted, %sh_prom 641 %masked = lshr i32 %highbitscleared, %sh_prom 642 ret i32 %masked 643} 644 645; 64-bit. 646 647define i64 @bextr64_d0(i64 %val, i64 %numskipbits, i64 %numlowbits) nounwind { 648; CHECK-LABEL: bextr64_d0: 649; CHECK: // %bb.0: 650; CHECK-NEXT: lsr x8, x0, x1 651; CHECK-NEXT: neg x9, x2 652; CHECK-NEXT: lsl x8, x8, x9 653; CHECK-NEXT: lsr x0, x8, x9 654; CHECK-NEXT: ret 655 %shifted = lshr i64 %val, %numskipbits 656 %numhighbits = sub i64 64, %numlowbits 657 %highbitscleared = shl i64 %shifted, %numhighbits 658 %masked = lshr i64 %highbitscleared, %numhighbits 659 ret i64 %masked 660} 661 662define i64 @bextr64_d1_indexzext(i64 %val, i8 %numskipbits, i8 %numlowbits) nounwind { 663; CHECK-LABEL: bextr64_d1_indexzext: 664; CHECK: // %bb.0: 665; CHECK-NEXT: orr w9, wzr, #0x40 666; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 667; CHECK-NEXT: lsr x8, x0, x1 668; CHECK-NEXT: sub w9, w9, w2 669; CHECK-NEXT: lsl x8, x8, x9 670; CHECK-NEXT: lsr x0, x8, x9 671; CHECK-NEXT: ret 672 %skip = zext i8 %numskipbits to i64 673 %shifted = lshr i64 %val, %skip 674 %numhighbits = sub i8 64, %numlowbits 675 %sh_prom = zext i8 %numhighbits to i64 676 %highbitscleared = shl i64 %shifted, %sh_prom 677 %masked = lshr i64 %highbitscleared, %sh_prom 678 ret i64 %masked 679} 680 681define i64 @bextr64_d2_load(i64* %w, i64 %numskipbits, i64 %numlowbits) nounwind { 682; CHECK-LABEL: bextr64_d2_load: 683; CHECK: // %bb.0: 684; CHECK-NEXT: ldr x8, [x0] 685; CHECK-NEXT: neg x9, x2 686; CHECK-NEXT: lsr x8, x8, x1 687; CHECK-NEXT: lsl x8, x8, x9 688; CHECK-NEXT: lsr x0, x8, x9 689; CHECK-NEXT: ret 690 %val = load i64, i64* %w 691 %shifted = lshr i64 %val, %numskipbits 692 %numhighbits = sub i64 64, %numlowbits 693 %highbitscleared = shl i64 %shifted, %numhighbits 694 %masked = lshr i64 %highbitscleared, %numhighbits 695 ret i64 %masked 696} 697 698define i64 @bextr64_d3_load_indexzext(i64* %w, i8 %numskipbits, i8 %numlowbits) nounwind { 699; CHECK-LABEL: bextr64_d3_load_indexzext: 700; CHECK: // %bb.0: 701; CHECK-NEXT: ldr x8, [x0] 702; CHECK-NEXT: orr w9, wzr, #0x40 703; CHECK-NEXT: // kill: def $w1 killed $w1 def $x1 704; CHECK-NEXT: sub w9, w9, w2 705; CHECK-NEXT: lsr x8, x8, x1 706; CHECK-NEXT: lsl x8, x8, x9 707; CHECK-NEXT: lsr x0, x8, x9 708; CHECK-NEXT: ret 709 %val = load i64, i64* %w 710 %skip = zext i8 %numskipbits to i64 711 %shifted = lshr i64 %val, %skip 712 %numhighbits = sub i8 64, %numlowbits 713 %sh_prom = zext i8 %numhighbits to i64 714 %highbitscleared = shl i64 %shifted, %sh_prom 715 %masked = lshr i64 %highbitscleared, %sh_prom 716 ret i64 %masked 717} 718 719; ---------------------------------------------------------------------------- ; 720; Constant 721; ---------------------------------------------------------------------------- ; 722 723; https://bugs.llvm.org/show_bug.cgi?id=38938 724define void @pr38938(i32* %a0, i64* %a1) { 725; CHECK-LABEL: pr38938: 726; CHECK: // %bb.0: 727; CHECK-NEXT: ldr x8, [x1] 728; CHECK-NEXT: ubfx x8, x8, #21, #10 729; CHECK-NEXT: lsl x8, x8, #2 730; CHECK-NEXT: ldr w9, [x0, x8] 731; CHECK-NEXT: add w9, w9, #1 // =1 732; CHECK-NEXT: str w9, [x0, x8] 733; CHECK-NEXT: ret 734 %tmp = load i64, i64* %a1, align 8 735 %tmp1 = lshr i64 %tmp, 21 736 %tmp2 = and i64 %tmp1, 1023 737 %tmp3 = getelementptr inbounds i32, i32* %a0, i64 %tmp2 738 %tmp4 = load i32, i32* %tmp3, align 4 739 %tmp5 = add nsw i32 %tmp4, 1 740 store i32 %tmp5, i32* %tmp3, align 4 741 ret void 742} 743 744; The most canonical variant 745define i32 @c0_i32(i32 %arg) { 746; CHECK-LABEL: c0_i32: 747; CHECK: // %bb.0: 748; CHECK-NEXT: ubfx w0, w0, #19, #10 749; CHECK-NEXT: ret 750 %tmp0 = lshr i32 %arg, 19 751 %tmp1 = and i32 %tmp0, 1023 752 ret i32 %tmp1 753} 754 755; Should be still fine, but the mask is shifted 756define i32 @c1_i32(i32 %arg) { 757; CHECK-LABEL: c1_i32: 758; CHECK: // %bb.0: 759; CHECK-NEXT: lsr w8, w0, #19 760; CHECK-NEXT: and w0, w8, #0xffc 761; CHECK-NEXT: ret 762 %tmp0 = lshr i32 %arg, 19 763 %tmp1 = and i32 %tmp0, 4092 764 ret i32 %tmp1 765} 766 767; Should be still fine, but the result is shifted left afterwards 768define i32 @c2_i32(i32 %arg) { 769; CHECK-LABEL: c2_i32: 770; CHECK: // %bb.0: 771; CHECK-NEXT: ubfx w8, w0, #19, #10 772; CHECK-NEXT: lsl w0, w8, #2 773; CHECK-NEXT: ret 774 %tmp0 = lshr i32 %arg, 19 775 %tmp1 = and i32 %tmp0, 1023 776 %tmp2 = shl i32 %tmp1, 2 777 ret i32 %tmp2 778} 779 780; The mask covers newly shifted-in bit 781define i32 @c4_i32_bad(i32 %arg) { 782; CHECK-LABEL: c4_i32_bad: 783; CHECK: // %bb.0: 784; CHECK-NEXT: lsr w8, w0, #19 785; CHECK-NEXT: and w0, w8, #0x1ffe 786; CHECK-NEXT: ret 787 %tmp0 = lshr i32 %arg, 19 788 %tmp1 = and i32 %tmp0, 16382 789 ret i32 %tmp1 790} 791 792; i64 793 794; The most canonical variant 795define i64 @c0_i64(i64 %arg) { 796; CHECK-LABEL: c0_i64: 797; CHECK: // %bb.0: 798; CHECK-NEXT: ubfx x0, x0, #51, #10 799; CHECK-NEXT: ret 800 %tmp0 = lshr i64 %arg, 51 801 %tmp1 = and i64 %tmp0, 1023 802 ret i64 %tmp1 803} 804 805; Should be still fine, but the mask is shifted 806define i64 @c1_i64(i64 %arg) { 807; CHECK-LABEL: c1_i64: 808; CHECK: // %bb.0: 809; CHECK-NEXT: lsr x8, x0, #51 810; CHECK-NEXT: and x0, x8, #0xffc 811; CHECK-NEXT: ret 812 %tmp0 = lshr i64 %arg, 51 813 %tmp1 = and i64 %tmp0, 4092 814 ret i64 %tmp1 815} 816 817; Should be still fine, but the result is shifted left afterwards 818define i64 @c2_i64(i64 %arg) { 819; CHECK-LABEL: c2_i64: 820; CHECK: // %bb.0: 821; CHECK-NEXT: ubfx x8, x0, #51, #10 822; CHECK-NEXT: lsl x0, x8, #2 823; CHECK-NEXT: ret 824 %tmp0 = lshr i64 %arg, 51 825 %tmp1 = and i64 %tmp0, 1023 826 %tmp2 = shl i64 %tmp1, 2 827 ret i64 %tmp2 828} 829 830; The mask covers newly shifted-in bit 831define i64 @c4_i64_bad(i64 %arg) { 832; CHECK-LABEL: c4_i64_bad: 833; CHECK: // %bb.0: 834; CHECK-NEXT: lsr x8, x0, #51 835; CHECK-NEXT: and x0, x8, #0x1ffe 836; CHECK-NEXT: ret 837 %tmp0 = lshr i64 %arg, 51 838 %tmp1 = and i64 %tmp0, 16382 839 ret i64 %tmp1 840} 841 842; ---------------------------------------------------------------------------- ; 843; Constant, storing the result afterwards. 844; ---------------------------------------------------------------------------- ; 845 846; i32 847 848; The most canonical variant 849define void @c5_i32(i32 %arg, i32* %ptr) { 850; CHECK-LABEL: c5_i32: 851; CHECK: // %bb.0: 852; CHECK-NEXT: ubfx w8, w0, #19, #10 853; CHECK-NEXT: str w8, [x1] 854; CHECK-NEXT: ret 855 %tmp0 = lshr i32 %arg, 19 856 %tmp1 = and i32 %tmp0, 1023 857 store i32 %tmp1, i32* %ptr 858 ret void 859} 860 861; Should be still fine, but the mask is shifted 862define void @c6_i32(i32 %arg, i32* %ptr) { 863; CHECK-LABEL: c6_i32: 864; CHECK: // %bb.0: 865; CHECK-NEXT: ubfx w8, w0, #19, #12 866; CHECK-NEXT: str w8, [x1] 867; CHECK-NEXT: ret 868 %tmp0 = lshr i32 %arg, 19 869 %tmp1 = and i32 %tmp0, 4095 870 store i32 %tmp1, i32* %ptr 871 ret void 872} 873 874; Should be still fine, but the result is shifted left afterwards 875define void @c7_i32(i32 %arg, i32* %ptr) { 876; CHECK-LABEL: c7_i32: 877; CHECK: // %bb.0: 878; CHECK-NEXT: ubfx w8, w0, #19, #10 879; CHECK-NEXT: lsl w8, w8, #2 880; CHECK-NEXT: str w8, [x1] 881; CHECK-NEXT: ret 882 %tmp0 = lshr i32 %arg, 19 883 %tmp1 = and i32 %tmp0, 1023 884 %tmp2 = shl i32 %tmp1, 2 885 store i32 %tmp2, i32* %ptr 886 ret void 887} 888 889; i64 890 891; The most canonical variant 892define void @c5_i64(i64 %arg, i64* %ptr) { 893; CHECK-LABEL: c5_i64: 894; CHECK: // %bb.0: 895; CHECK-NEXT: ubfx x8, x0, #51, #10 896; CHECK-NEXT: str x8, [x1] 897; CHECK-NEXT: ret 898 %tmp0 = lshr i64 %arg, 51 899 %tmp1 = and i64 %tmp0, 1023 900 store i64 %tmp1, i64* %ptr 901 ret void 902} 903 904; Should be still fine, but the mask is shifted 905define void @c6_i64(i64 %arg, i64* %ptr) { 906; CHECK-LABEL: c6_i64: 907; CHECK: // %bb.0: 908; CHECK-NEXT: ubfx x8, x0, #51, #12 909; CHECK-NEXT: str x8, [x1] 910; CHECK-NEXT: ret 911 %tmp0 = lshr i64 %arg, 51 912 %tmp1 = and i64 %tmp0, 4095 913 store i64 %tmp1, i64* %ptr 914 ret void 915} 916 917; Should be still fine, but the result is shifted left afterwards 918define void @c7_i64(i64 %arg, i64* %ptr) { 919; CHECK-LABEL: c7_i64: 920; CHECK: // %bb.0: 921; CHECK-NEXT: ubfx x8, x0, #51, #10 922; CHECK-NEXT: lsl x8, x8, #2 923; CHECK-NEXT: str x8, [x1] 924; CHECK-NEXT: ret 925 %tmp0 = lshr i64 %arg, 51 926 %tmp1 = and i64 %tmp0, 1023 927 %tmp2 = shl i64 %tmp1, 2 928 store i64 %tmp2, i64* %ptr 929 ret void 930} 931