1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=aarch64-unknown-unknown | FileCheck %s 3 4;==============================================================================; 5; the shift amount is negated (shiftbitwidth - shiftamt) 6;==============================================================================; 7 8; shift left 9;------------------------------------------------------------------------------; 10 11define i32 @reg32_shl_by_negated(i32 %val, i32 %shamt) nounwind { 12; CHECK-LABEL: reg32_shl_by_negated: 13; CHECK: // %bb.0: 14; CHECK-NEXT: neg w8, w1 15; CHECK-NEXT: lsl w0, w0, w8 16; CHECK-NEXT: ret 17 %negshamt = sub i32 32, %shamt 18 %shifted = shl i32 %val, %negshamt 19 ret i32 %shifted 20} 21define i32 @load32_shl_by_negated(i32* %valptr, i32 %shamt) nounwind { 22; CHECK-LABEL: load32_shl_by_negated: 23; CHECK: // %bb.0: 24; CHECK-NEXT: neg w8, w1 25; CHECK-NEXT: ldr w9, [x0] 26; CHECK-NEXT: lsl w0, w9, w8 27; CHECK-NEXT: ret 28 %val = load i32, i32* %valptr 29 %negshamt = sub i32 32, %shamt 30 %shifted = shl i32 %val, %negshamt 31 ret i32 %shifted 32} 33define void @store32_shl_by_negated(i32 %val, i32* %dstptr, i32 %shamt) nounwind { 34; CHECK-LABEL: store32_shl_by_negated: 35; CHECK: // %bb.0: 36; CHECK-NEXT: neg w8, w2 37; CHECK-NEXT: lsl w8, w0, w8 38; CHECK-NEXT: str w8, [x1] 39; CHECK-NEXT: ret 40 %negshamt = sub i32 32, %shamt 41 %shifted = shl i32 %val, %negshamt 42 store i32 %shifted, i32* %dstptr 43 ret void 44} 45define void @modify32_shl_by_negated(i32* %valptr, i32 %shamt) nounwind { 46; CHECK-LABEL: modify32_shl_by_negated: 47; CHECK: // %bb.0: 48; CHECK-NEXT: neg w8, w1 49; CHECK-NEXT: ldr w9, [x0] 50; CHECK-NEXT: lsl w8, w9, w8 51; CHECK-NEXT: str w8, [x0] 52; CHECK-NEXT: ret 53 %val = load i32, i32* %valptr 54 %negshamt = sub i32 32, %shamt 55 %shifted = shl i32 %val, %negshamt 56 store i32 %shifted, i32* %valptr 57 ret void 58} 59 60define i64 @reg64_shl_by_negated(i64 %val, i64 %shamt) nounwind { 61; CHECK-LABEL: reg64_shl_by_negated: 62; CHECK: // %bb.0: 63; CHECK-NEXT: neg x8, x1 64; CHECK-NEXT: lsl x0, x0, x8 65; CHECK-NEXT: ret 66 %negshamt = sub i64 64, %shamt 67 %shifted = shl i64 %val, %negshamt 68 ret i64 %shifted 69} 70define i64 @load64_shl_by_negated(i64* %valptr, i64 %shamt) nounwind { 71; CHECK-LABEL: load64_shl_by_negated: 72; CHECK: // %bb.0: 73; CHECK-NEXT: neg x8, x1 74; CHECK-NEXT: ldr x9, [x0] 75; CHECK-NEXT: lsl x0, x9, x8 76; CHECK-NEXT: ret 77 %val = load i64, i64* %valptr 78 %negshamt = sub i64 64, %shamt 79 %shifted = shl i64 %val, %negshamt 80 ret i64 %shifted 81} 82define void @store64_shl_by_negated(i64 %val, i64* %dstptr, i64 %shamt) nounwind { 83; CHECK-LABEL: store64_shl_by_negated: 84; CHECK: // %bb.0: 85; CHECK-NEXT: neg x8, x2 86; CHECK-NEXT: lsl x8, x0, x8 87; CHECK-NEXT: str x8, [x1] 88; CHECK-NEXT: ret 89 %negshamt = sub i64 64, %shamt 90 %shifted = shl i64 %val, %negshamt 91 store i64 %shifted, i64* %dstptr 92 ret void 93} 94define void @modify64_shl_by_negated(i64* %valptr, i64 %shamt) nounwind { 95; CHECK-LABEL: modify64_shl_by_negated: 96; CHECK: // %bb.0: 97; CHECK-NEXT: neg x8, x1 98; CHECK-NEXT: ldr x9, [x0] 99; CHECK-NEXT: lsl x8, x9, x8 100; CHECK-NEXT: str x8, [x0] 101; CHECK-NEXT: ret 102 %val = load i64, i64* %valptr 103 %negshamt = sub i64 64, %shamt 104 %shifted = shl i64 %val, %negshamt 105 store i64 %shifted, i64* %valptr 106 ret void 107} 108 109; logical shift right 110;------------------------------------------------------------------------------; 111 112define i32 @reg32_lshr_by_negated(i32 %val, i32 %shamt) nounwind { 113; CHECK-LABEL: reg32_lshr_by_negated: 114; CHECK: // %bb.0: 115; CHECK-NEXT: neg w8, w1 116; CHECK-NEXT: lsr w0, w0, w8 117; CHECK-NEXT: ret 118 %negshamt = sub i32 32, %shamt 119 %shifted = lshr i32 %val, %negshamt 120 ret i32 %shifted 121} 122define i32 @load32_lshr_by_negated(i32* %valptr, i32 %shamt) nounwind { 123; CHECK-LABEL: load32_lshr_by_negated: 124; CHECK: // %bb.0: 125; CHECK-NEXT: neg w8, w1 126; CHECK-NEXT: ldr w9, [x0] 127; CHECK-NEXT: lsr w0, w9, w8 128; CHECK-NEXT: ret 129 %val = load i32, i32* %valptr 130 %negshamt = sub i32 32, %shamt 131 %shifted = lshr i32 %val, %negshamt 132 ret i32 %shifted 133} 134define void @store32_lshr_by_negated(i32 %val, i32* %dstptr, i32 %shamt) nounwind { 135; CHECK-LABEL: store32_lshr_by_negated: 136; CHECK: // %bb.0: 137; CHECK-NEXT: neg w8, w2 138; CHECK-NEXT: lsr w8, w0, w8 139; CHECK-NEXT: str w8, [x1] 140; CHECK-NEXT: ret 141 %negshamt = sub i32 32, %shamt 142 %shifted = lshr i32 %val, %negshamt 143 store i32 %shifted, i32* %dstptr 144 ret void 145} 146define void @modify32_lshr_by_negated(i32* %valptr, i32 %shamt) nounwind { 147; CHECK-LABEL: modify32_lshr_by_negated: 148; CHECK: // %bb.0: 149; CHECK-NEXT: neg w8, w1 150; CHECK-NEXT: ldr w9, [x0] 151; CHECK-NEXT: lsr w8, w9, w8 152; CHECK-NEXT: str w8, [x0] 153; CHECK-NEXT: ret 154 %val = load i32, i32* %valptr 155 %negshamt = sub i32 32, %shamt 156 %shifted = lshr i32 %val, %negshamt 157 store i32 %shifted, i32* %valptr 158 ret void 159} 160 161define i64 @reg64_lshr_by_negated(i64 %val, i64 %shamt) nounwind { 162; CHECK-LABEL: reg64_lshr_by_negated: 163; CHECK: // %bb.0: 164; CHECK-NEXT: neg x8, x1 165; CHECK-NEXT: lsr x0, x0, x8 166; CHECK-NEXT: ret 167 %negshamt = sub i64 64, %shamt 168 %shifted = lshr i64 %val, %negshamt 169 ret i64 %shifted 170} 171define i64 @load64_lshr_by_negated(i64* %valptr, i64 %shamt) nounwind { 172; CHECK-LABEL: load64_lshr_by_negated: 173; CHECK: // %bb.0: 174; CHECK-NEXT: neg x8, x1 175; CHECK-NEXT: ldr x9, [x0] 176; CHECK-NEXT: lsr x0, x9, x8 177; CHECK-NEXT: ret 178 %val = load i64, i64* %valptr 179 %negshamt = sub i64 64, %shamt 180 %shifted = lshr i64 %val, %negshamt 181 ret i64 %shifted 182} 183define void @store64_lshr_by_negated(i64 %val, i64* %dstptr, i64 %shamt) nounwind { 184; CHECK-LABEL: store64_lshr_by_negated: 185; CHECK: // %bb.0: 186; CHECK-NEXT: neg x8, x2 187; CHECK-NEXT: lsr x8, x0, x8 188; CHECK-NEXT: str x8, [x1] 189; CHECK-NEXT: ret 190 %negshamt = sub i64 64, %shamt 191 %shifted = lshr i64 %val, %negshamt 192 store i64 %shifted, i64* %dstptr 193 ret void 194} 195define void @modify64_lshr_by_negated(i64* %valptr, i64 %shamt) nounwind { 196; CHECK-LABEL: modify64_lshr_by_negated: 197; CHECK: // %bb.0: 198; CHECK-NEXT: neg x8, x1 199; CHECK-NEXT: ldr x9, [x0] 200; CHECK-NEXT: lsr x8, x9, x8 201; CHECK-NEXT: str x8, [x0] 202; CHECK-NEXT: ret 203 %val = load i64, i64* %valptr 204 %negshamt = sub i64 64, %shamt 205 %shifted = lshr i64 %val, %negshamt 206 store i64 %shifted, i64* %valptr 207 ret void 208} 209 210; arithmetic shift right 211;------------------------------------------------------------------------------; 212 213define i32 @reg32_ashr_by_negated(i32 %val, i32 %shamt) nounwind { 214; CHECK-LABEL: reg32_ashr_by_negated: 215; CHECK: // %bb.0: 216; CHECK-NEXT: neg w8, w1 217; CHECK-NEXT: asr w0, w0, w8 218; CHECK-NEXT: ret 219 %negshamt = sub i32 32, %shamt 220 %shifted = ashr i32 %val, %negshamt 221 ret i32 %shifted 222} 223define i32 @load32_ashr_by_negated(i32* %valptr, i32 %shamt) nounwind { 224; CHECK-LABEL: load32_ashr_by_negated: 225; CHECK: // %bb.0: 226; CHECK-NEXT: neg w8, w1 227; CHECK-NEXT: ldr w9, [x0] 228; CHECK-NEXT: asr w0, w9, w8 229; CHECK-NEXT: ret 230 %val = load i32, i32* %valptr 231 %negshamt = sub i32 32, %shamt 232 %shifted = ashr i32 %val, %negshamt 233 ret i32 %shifted 234} 235define void @store32_ashr_by_negated(i32 %val, i32* %dstptr, i32 %shamt) nounwind { 236; CHECK-LABEL: store32_ashr_by_negated: 237; CHECK: // %bb.0: 238; CHECK-NEXT: neg w8, w2 239; CHECK-NEXT: asr w8, w0, w8 240; CHECK-NEXT: str w8, [x1] 241; CHECK-NEXT: ret 242 %negshamt = sub i32 32, %shamt 243 %shifted = ashr i32 %val, %negshamt 244 store i32 %shifted, i32* %dstptr 245 ret void 246} 247define void @modify32_ashr_by_negated(i32* %valptr, i32 %shamt) nounwind { 248; CHECK-LABEL: modify32_ashr_by_negated: 249; CHECK: // %bb.0: 250; CHECK-NEXT: neg w8, w1 251; CHECK-NEXT: ldr w9, [x0] 252; CHECK-NEXT: asr w8, w9, w8 253; CHECK-NEXT: str w8, [x0] 254; CHECK-NEXT: ret 255 %val = load i32, i32* %valptr 256 %negshamt = sub i32 32, %shamt 257 %shifted = ashr i32 %val, %negshamt 258 store i32 %shifted, i32* %valptr 259 ret void 260} 261 262define i64 @reg64_ashr_by_negated(i64 %val, i64 %shamt) nounwind { 263; CHECK-LABEL: reg64_ashr_by_negated: 264; CHECK: // %bb.0: 265; CHECK-NEXT: neg x8, x1 266; CHECK-NEXT: asr x0, x0, x8 267; CHECK-NEXT: ret 268 %negshamt = sub i64 64, %shamt 269 %shifted = ashr i64 %val, %negshamt 270 ret i64 %shifted 271} 272define i64 @load64_ashr_by_negated(i64* %valptr, i64 %shamt) nounwind { 273; CHECK-LABEL: load64_ashr_by_negated: 274; CHECK: // %bb.0: 275; CHECK-NEXT: neg x8, x1 276; CHECK-NEXT: ldr x9, [x0] 277; CHECK-NEXT: asr x0, x9, x8 278; CHECK-NEXT: ret 279 %val = load i64, i64* %valptr 280 %negshamt = sub i64 64, %shamt 281 %shifted = ashr i64 %val, %negshamt 282 ret i64 %shifted 283} 284define void @store64_ashr_by_negated(i64 %val, i64* %dstptr, i64 %shamt) nounwind { 285; CHECK-LABEL: store64_ashr_by_negated: 286; CHECK: // %bb.0: 287; CHECK-NEXT: neg x8, x2 288; CHECK-NEXT: asr x8, x0, x8 289; CHECK-NEXT: str x8, [x1] 290; CHECK-NEXT: ret 291 %negshamt = sub i64 64, %shamt 292 %shifted = ashr i64 %val, %negshamt 293 store i64 %shifted, i64* %dstptr 294 ret void 295} 296define void @modify64_ashr_by_negated(i64* %valptr, i64 %shamt) nounwind { 297; CHECK-LABEL: modify64_ashr_by_negated: 298; CHECK: // %bb.0: 299; CHECK-NEXT: neg x8, x1 300; CHECK-NEXT: ldr x9, [x0] 301; CHECK-NEXT: asr x8, x9, x8 302; CHECK-NEXT: str x8, [x0] 303; CHECK-NEXT: ret 304 %val = load i64, i64* %valptr 305 %negshamt = sub i64 64, %shamt 306 %shifted = ashr i64 %val, %negshamt 307 store i64 %shifted, i64* %valptr 308 ret void 309} 310 311;==============================================================================; 312; the shift amount is complemented (shiftbitwidth - 1 - shiftamt) 313;==============================================================================; 314 315; shift left 316;------------------------------------------------------------------------------; 317 318define i32 @reg32_shl_by_complemented(i32 %val, i32 %shamt) nounwind { 319; CHECK-LABEL: reg32_shl_by_complemented: 320; CHECK: // %bb.0: 321; CHECK-NEXT: mov w8, #31 322; CHECK-NEXT: sub w8, w8, w1 323; CHECK-NEXT: lsl w0, w0, w8 324; CHECK-NEXT: ret 325 %negshamt = sub i32 31, %shamt 326 %shifted = shl i32 %val, %negshamt 327 ret i32 %shifted 328} 329define i32 @load32_shl_by_complemented(i32* %valptr, i32 %shamt) nounwind { 330; CHECK-LABEL: load32_shl_by_complemented: 331; CHECK: // %bb.0: 332; CHECK-NEXT: mov w8, #31 333; CHECK-NEXT: ldr w9, [x0] 334; CHECK-NEXT: sub w8, w8, w1 335; CHECK-NEXT: lsl w0, w9, w8 336; CHECK-NEXT: ret 337 %val = load i32, i32* %valptr 338 %negshamt = sub i32 31, %shamt 339 %shifted = shl i32 %val, %negshamt 340 ret i32 %shifted 341} 342define void @store32_shl_by_complemented(i32 %val, i32* %dstptr, i32 %shamt) nounwind { 343; CHECK-LABEL: store32_shl_by_complemented: 344; CHECK: // %bb.0: 345; CHECK-NEXT: mov w8, #31 346; CHECK-NEXT: sub w8, w8, w2 347; CHECK-NEXT: lsl w8, w0, w8 348; CHECK-NEXT: str w8, [x1] 349; CHECK-NEXT: ret 350 %negshamt = sub i32 31, %shamt 351 %shifted = shl i32 %val, %negshamt 352 store i32 %shifted, i32* %dstptr 353 ret void 354} 355define void @modify32_shl_by_complemented(i32* %valptr, i32 %shamt) nounwind { 356; CHECK-LABEL: modify32_shl_by_complemented: 357; CHECK: // %bb.0: 358; CHECK-NEXT: mov w8, #31 359; CHECK-NEXT: ldr w9, [x0] 360; CHECK-NEXT: sub w8, w8, w1 361; CHECK-NEXT: lsl w8, w9, w8 362; CHECK-NEXT: str w8, [x0] 363; CHECK-NEXT: ret 364 %val = load i32, i32* %valptr 365 %negshamt = sub i32 31, %shamt 366 %shifted = shl i32 %val, %negshamt 367 store i32 %shifted, i32* %valptr 368 ret void 369} 370 371define i64 @reg64_shl_by_complemented(i64 %val, i64 %shamt) nounwind { 372; CHECK-LABEL: reg64_shl_by_complemented: 373; CHECK: // %bb.0: 374; CHECK-NEXT: mov w8, #63 375; CHECK-NEXT: sub x8, x8, x1 376; CHECK-NEXT: lsl x0, x0, x8 377; CHECK-NEXT: ret 378 %negshamt = sub i64 63, %shamt 379 %shifted = shl i64 %val, %negshamt 380 ret i64 %shifted 381} 382define i64 @load64_shl_by_complemented(i64* %valptr, i64 %shamt) nounwind { 383; CHECK-LABEL: load64_shl_by_complemented: 384; CHECK: // %bb.0: 385; CHECK-NEXT: mov w8, #63 386; CHECK-NEXT: ldr x9, [x0] 387; CHECK-NEXT: sub x8, x8, x1 388; CHECK-NEXT: lsl x0, x9, x8 389; CHECK-NEXT: ret 390 %val = load i64, i64* %valptr 391 %negshamt = sub i64 63, %shamt 392 %shifted = shl i64 %val, %negshamt 393 ret i64 %shifted 394} 395define void @store64_shl_by_complemented(i64 %val, i64* %dstptr, i64 %shamt) nounwind { 396; CHECK-LABEL: store64_shl_by_complemented: 397; CHECK: // %bb.0: 398; CHECK-NEXT: mov w8, #63 399; CHECK-NEXT: sub x8, x8, x2 400; CHECK-NEXT: lsl x8, x0, x8 401; CHECK-NEXT: str x8, [x1] 402; CHECK-NEXT: ret 403 %negshamt = sub i64 63, %shamt 404 %shifted = shl i64 %val, %negshamt 405 store i64 %shifted, i64* %dstptr 406 ret void 407} 408define void @modify64_shl_by_complemented(i64* %valptr, i64 %shamt) nounwind { 409; CHECK-LABEL: modify64_shl_by_complemented: 410; CHECK: // %bb.0: 411; CHECK-NEXT: mov w8, #63 412; CHECK-NEXT: ldr x9, [x0] 413; CHECK-NEXT: sub x8, x8, x1 414; CHECK-NEXT: lsl x8, x9, x8 415; CHECK-NEXT: str x8, [x0] 416; CHECK-NEXT: ret 417 %val = load i64, i64* %valptr 418 %negshamt = sub i64 63, %shamt 419 %shifted = shl i64 %val, %negshamt 420 store i64 %shifted, i64* %valptr 421 ret void 422} 423 424; logical shift right 425;------------------------------------------------------------------------------; 426 427define i32 @reg32_lshr_by_complemented(i32 %val, i32 %shamt) nounwind { 428; CHECK-LABEL: reg32_lshr_by_complemented: 429; CHECK: // %bb.0: 430; CHECK-NEXT: mov w8, #31 431; CHECK-NEXT: sub w8, w8, w1 432; CHECK-NEXT: lsr w0, w0, w8 433; CHECK-NEXT: ret 434 %negshamt = sub i32 31, %shamt 435 %shifted = lshr i32 %val, %negshamt 436 ret i32 %shifted 437} 438define i32 @load32_lshr_by_complemented(i32* %valptr, i32 %shamt) nounwind { 439; CHECK-LABEL: load32_lshr_by_complemented: 440; CHECK: // %bb.0: 441; CHECK-NEXT: mov w8, #31 442; CHECK-NEXT: ldr w9, [x0] 443; CHECK-NEXT: sub w8, w8, w1 444; CHECK-NEXT: lsr w0, w9, w8 445; CHECK-NEXT: ret 446 %val = load i32, i32* %valptr 447 %negshamt = sub i32 31, %shamt 448 %shifted = lshr i32 %val, %negshamt 449 ret i32 %shifted 450} 451define void @store32_lshr_by_complemented(i32 %val, i32* %dstptr, i32 %shamt) nounwind { 452; CHECK-LABEL: store32_lshr_by_complemented: 453; CHECK: // %bb.0: 454; CHECK-NEXT: mov w8, #31 455; CHECK-NEXT: sub w8, w8, w2 456; CHECK-NEXT: lsr w8, w0, w8 457; CHECK-NEXT: str w8, [x1] 458; CHECK-NEXT: ret 459 %negshamt = sub i32 31, %shamt 460 %shifted = lshr i32 %val, %negshamt 461 store i32 %shifted, i32* %dstptr 462 ret void 463} 464define void @modify32_lshr_by_complemented(i32* %valptr, i32 %shamt) nounwind { 465; CHECK-LABEL: modify32_lshr_by_complemented: 466; CHECK: // %bb.0: 467; CHECK-NEXT: mov w8, #31 468; CHECK-NEXT: ldr w9, [x0] 469; CHECK-NEXT: sub w8, w8, w1 470; CHECK-NEXT: lsr w8, w9, w8 471; CHECK-NEXT: str w8, [x0] 472; CHECK-NEXT: ret 473 %val = load i32, i32* %valptr 474 %negshamt = sub i32 31, %shamt 475 %shifted = lshr i32 %val, %negshamt 476 store i32 %shifted, i32* %valptr 477 ret void 478} 479 480define i64 @reg64_lshr_by_complemented(i64 %val, i64 %shamt) nounwind { 481; CHECK-LABEL: reg64_lshr_by_complemented: 482; CHECK: // %bb.0: 483; CHECK-NEXT: mov w8, #63 484; CHECK-NEXT: sub x8, x8, x1 485; CHECK-NEXT: lsr x0, x0, x8 486; CHECK-NEXT: ret 487 %negshamt = sub i64 63, %shamt 488 %shifted = lshr i64 %val, %negshamt 489 ret i64 %shifted 490} 491define i64 @load64_lshr_by_complemented(i64* %valptr, i64 %shamt) nounwind { 492; CHECK-LABEL: load64_lshr_by_complemented: 493; CHECK: // %bb.0: 494; CHECK-NEXT: mov w8, #63 495; CHECK-NEXT: ldr x9, [x0] 496; CHECK-NEXT: sub x8, x8, x1 497; CHECK-NEXT: lsr x0, x9, x8 498; CHECK-NEXT: ret 499 %val = load i64, i64* %valptr 500 %negshamt = sub i64 63, %shamt 501 %shifted = lshr i64 %val, %negshamt 502 ret i64 %shifted 503} 504define void @store64_lshr_by_complemented(i64 %val, i64* %dstptr, i64 %shamt) nounwind { 505; CHECK-LABEL: store64_lshr_by_complemented: 506; CHECK: // %bb.0: 507; CHECK-NEXT: mov w8, #63 508; CHECK-NEXT: sub x8, x8, x2 509; CHECK-NEXT: lsr x8, x0, x8 510; CHECK-NEXT: str x8, [x1] 511; CHECK-NEXT: ret 512 %negshamt = sub i64 63, %shamt 513 %shifted = lshr i64 %val, %negshamt 514 store i64 %shifted, i64* %dstptr 515 ret void 516} 517define void @modify64_lshr_by_complemented(i64* %valptr, i64 %shamt) nounwind { 518; CHECK-LABEL: modify64_lshr_by_complemented: 519; CHECK: // %bb.0: 520; CHECK-NEXT: mov w8, #63 521; CHECK-NEXT: ldr x9, [x0] 522; CHECK-NEXT: sub x8, x8, x1 523; CHECK-NEXT: lsr x8, x9, x8 524; CHECK-NEXT: str x8, [x0] 525; CHECK-NEXT: ret 526 %val = load i64, i64* %valptr 527 %negshamt = sub i64 63, %shamt 528 %shifted = lshr i64 %val, %negshamt 529 store i64 %shifted, i64* %valptr 530 ret void 531} 532 533; arithmetic shift right 534;------------------------------------------------------------------------------; 535 536define i32 @reg32_ashr_by_complemented(i32 %val, i32 %shamt) nounwind { 537; CHECK-LABEL: reg32_ashr_by_complemented: 538; CHECK: // %bb.0: 539; CHECK-NEXT: mov w8, #31 540; CHECK-NEXT: sub w8, w8, w1 541; CHECK-NEXT: asr w0, w0, w8 542; CHECK-NEXT: ret 543 %negshamt = sub i32 31, %shamt 544 %shifted = ashr i32 %val, %negshamt 545 ret i32 %shifted 546} 547define i32 @load32_ashr_by_complemented(i32* %valptr, i32 %shamt) nounwind { 548; CHECK-LABEL: load32_ashr_by_complemented: 549; CHECK: // %bb.0: 550; CHECK-NEXT: mov w8, #31 551; CHECK-NEXT: ldr w9, [x0] 552; CHECK-NEXT: sub w8, w8, w1 553; CHECK-NEXT: asr w0, w9, w8 554; CHECK-NEXT: ret 555 %val = load i32, i32* %valptr 556 %negshamt = sub i32 31, %shamt 557 %shifted = ashr i32 %val, %negshamt 558 ret i32 %shifted 559} 560define void @store32_ashr_by_complemented(i32 %val, i32* %dstptr, i32 %shamt) nounwind { 561; CHECK-LABEL: store32_ashr_by_complemented: 562; CHECK: // %bb.0: 563; CHECK-NEXT: mov w8, #31 564; CHECK-NEXT: sub w8, w8, w2 565; CHECK-NEXT: asr w8, w0, w8 566; CHECK-NEXT: str w8, [x1] 567; CHECK-NEXT: ret 568 %negshamt = sub i32 31, %shamt 569 %shifted = ashr i32 %val, %negshamt 570 store i32 %shifted, i32* %dstptr 571 ret void 572} 573define void @modify32_ashr_by_complemented(i32* %valptr, i32 %shamt) nounwind { 574; CHECK-LABEL: modify32_ashr_by_complemented: 575; CHECK: // %bb.0: 576; CHECK-NEXT: mov w8, #31 577; CHECK-NEXT: ldr w9, [x0] 578; CHECK-NEXT: sub w8, w8, w1 579; CHECK-NEXT: asr w8, w9, w8 580; CHECK-NEXT: str w8, [x0] 581; CHECK-NEXT: ret 582 %val = load i32, i32* %valptr 583 %negshamt = sub i32 31, %shamt 584 %shifted = ashr i32 %val, %negshamt 585 store i32 %shifted, i32* %valptr 586 ret void 587} 588 589define i64 @reg64_ashr_by_complemented(i64 %val, i64 %shamt) nounwind { 590; CHECK-LABEL: reg64_ashr_by_complemented: 591; CHECK: // %bb.0: 592; CHECK-NEXT: mov w8, #63 593; CHECK-NEXT: sub x8, x8, x1 594; CHECK-NEXT: asr x0, x0, x8 595; CHECK-NEXT: ret 596 %negshamt = sub i64 63, %shamt 597 %shifted = ashr i64 %val, %negshamt 598 ret i64 %shifted 599} 600define i64 @load64_ashr_by_complemented(i64* %valptr, i64 %shamt) nounwind { 601; CHECK-LABEL: load64_ashr_by_complemented: 602; CHECK: // %bb.0: 603; CHECK-NEXT: mov w8, #63 604; CHECK-NEXT: ldr x9, [x0] 605; CHECK-NEXT: sub x8, x8, x1 606; CHECK-NEXT: asr x0, x9, x8 607; CHECK-NEXT: ret 608 %val = load i64, i64* %valptr 609 %negshamt = sub i64 63, %shamt 610 %shifted = ashr i64 %val, %negshamt 611 ret i64 %shifted 612} 613define void @store64_ashr_by_complemented(i64 %val, i64* %dstptr, i64 %shamt) nounwind { 614; CHECK-LABEL: store64_ashr_by_complemented: 615; CHECK: // %bb.0: 616; CHECK-NEXT: mov w8, #63 617; CHECK-NEXT: sub x8, x8, x2 618; CHECK-NEXT: asr x8, x0, x8 619; CHECK-NEXT: str x8, [x1] 620; CHECK-NEXT: ret 621 %negshamt = sub i64 63, %shamt 622 %shifted = ashr i64 %val, %negshamt 623 store i64 %shifted, i64* %dstptr 624 ret void 625} 626define void @modify64_ashr_by_complemented(i64* %valptr, i64 %shamt) nounwind { 627; CHECK-LABEL: modify64_ashr_by_complemented: 628; CHECK: // %bb.0: 629; CHECK-NEXT: mov w8, #63 630; CHECK-NEXT: ldr x9, [x0] 631; CHECK-NEXT: sub x8, x8, x1 632; CHECK-NEXT: asr x8, x9, x8 633; CHECK-NEXT: str x8, [x0] 634; CHECK-NEXT: ret 635 %val = load i64, i64* %valptr 636 %negshamt = sub i64 63, %shamt 637 %shifted = ashr i64 %val, %negshamt 638 store i64 %shifted, i64* %valptr 639 ret void 640} 641 642;||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||; 643; next let's only test simple reg pattern, and only lshr. 644;||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||; 645 646;==============================================================================; 647; subtraction from negated shift amount 648 649define i32 @reg32_lshr_by_sub_from_negated(i32 %val, i32 %a, i32 %b) nounwind { 650; CHECK-LABEL: reg32_lshr_by_sub_from_negated: 651; CHECK: // %bb.0: 652; CHECK-NEXT: add w8, w1, w2 653; CHECK-NEXT: neg w8, w8 654; CHECK-NEXT: lsr w0, w0, w8 655; CHECK-NEXT: ret 656 %nega = sub i32 32, %a 657 %negasubb = sub i32 %nega, %b 658 %shifted = lshr i32 %val, %negasubb 659 ret i32 %shifted 660} 661define i64 @reg64_lshr_by_sub_from_negated(i64 %val, i64 %a, i64 %b) nounwind { 662; CHECK-LABEL: reg64_lshr_by_sub_from_negated: 663; CHECK: // %bb.0: 664; CHECK-NEXT: add x8, x1, x2 665; CHECK-NEXT: neg x8, x8 666; CHECK-NEXT: lsr x0, x0, x8 667; CHECK-NEXT: ret 668 %nega = sub i64 64, %a 669 %negasubb = sub i64 %nega, %b 670 %shifted = lshr i64 %val, %negasubb 671 ret i64 %shifted 672} 673 674;==============================================================================; 675; subtraction of negated shift amount 676 677define i32 @reg32_lshr_by_sub_of_negated(i32 %val, i32 %a, i32 %b) nounwind { 678; CHECK-LABEL: reg32_lshr_by_sub_of_negated: 679; CHECK: // %bb.0: 680; CHECK-NEXT: add w8, w1, w2 681; CHECK-NEXT: lsr w0, w0, w8 682; CHECK-NEXT: ret 683 %nega = sub i32 32, %a 684 %negasubb = sub i32 %b, %nega 685 %shifted = lshr i32 %val, %negasubb 686 ret i32 %shifted 687} 688define i64 @reg64_lshr_by_sub_of_negated(i64 %val, i64 %a, i64 %b) nounwind { 689; CHECK-LABEL: reg64_lshr_by_sub_of_negated: 690; CHECK: // %bb.0: 691; CHECK-NEXT: add x8, x1, x2 692; CHECK-NEXT: lsr x0, x0, x8 693; CHECK-NEXT: ret 694 %nega = sub i64 64, %a 695 %negasubb = sub i64 %b, %nega 696 %shifted = lshr i64 %val, %negasubb 697 ret i64 %shifted 698} 699 700;==============================================================================; 701; add to negated shift amount 702; 703 704define i32 @reg32_lshr_by_add_to_negated(i32 %val, i32 %a, i32 %b) nounwind { 705; CHECK-LABEL: reg32_lshr_by_add_to_negated: 706; CHECK: // %bb.0: 707; CHECK-NEXT: sub w8, w2, w1 708; CHECK-NEXT: lsr w0, w0, w8 709; CHECK-NEXT: ret 710 %nega = sub i32 32, %a 711 %negasubb = add i32 %nega, %b 712 %shifted = lshr i32 %val, %negasubb 713 ret i32 %shifted 714} 715define i64 @reg64_lshr_by_add_to_negated(i64 %val, i64 %a, i64 %b) nounwind { 716; CHECK-LABEL: reg64_lshr_by_add_to_negated: 717; CHECK: // %bb.0: 718; CHECK-NEXT: sub x8, x2, x1 719; CHECK-NEXT: lsr x0, x0, x8 720; CHECK-NEXT: ret 721 %nega = sub i64 64, %a 722 %negasubb = add i64 %nega, %b 723 %shifted = lshr i64 %val, %negasubb 724 ret i64 %shifted 725} 726 727;==============================================================================; 728; subtraction of negated shift amounts 729 730define i32 @reg32_lshr_by_sub_of_negated_amts(i32 %val, i32 %a, i32 %b) nounwind { 731; CHECK-LABEL: reg32_lshr_by_sub_of_negated_amts: 732; CHECK: // %bb.0: 733; CHECK-NEXT: sub w8, w2, w1 734; CHECK-NEXT: lsr w0, w0, w8 735; CHECK-NEXT: ret 736 %nega = sub i32 32, %a 737 %negb = sub i32 32, %b 738 %negasubnegb = sub i32 %nega, %negb 739 %shifted = lshr i32 %val, %negasubnegb 740 ret i32 %shifted 741} 742define i64 @reg64_lshr_by_sub_of_negated_amts(i64 %val, i64 %a, i64 %b) nounwind { 743; CHECK-LABEL: reg64_lshr_by_sub_of_negated_amts: 744; CHECK: // %bb.0: 745; CHECK-NEXT: sub x8, x2, x1 746; CHECK-NEXT: lsr x0, x0, x8 747; CHECK-NEXT: ret 748 %nega = sub i64 64, %a 749 %negb = sub i64 64, %b 750 %negasubnegb = sub i64 %nega, %negb 751 %shifted = lshr i64 %val, %negasubnegb 752 ret i64 %shifted 753} 754 755;==============================================================================; 756; addition of negated shift amounts 757 758define i32 @reg32_lshr_by_add_of_negated_amts(i32 %val, i32 %a, i32 %b) nounwind { 759; CHECK-LABEL: reg32_lshr_by_add_of_negated_amts: 760; CHECK: // %bb.0: 761; CHECK-NEXT: add w8, w1, w2 762; CHECK-NEXT: neg w8, w8 763; CHECK-NEXT: lsr w0, w0, w8 764; CHECK-NEXT: ret 765 %nega = sub i32 32, %a 766 %negb = sub i32 32, %b 767 %negasubnegb = add i32 %nega, %negb 768 %shifted = lshr i32 %val, %negasubnegb 769 ret i32 %shifted 770} 771define i64 @reg64_lshr_by_add_of_negated_amts(i64 %val, i64 %a, i64 %b) nounwind { 772; CHECK-LABEL: reg64_lshr_by_add_of_negated_amts: 773; CHECK: // %bb.0: 774; CHECK-NEXT: add x8, x1, x2 775; CHECK-NEXT: neg x8, x8 776; CHECK-NEXT: lsr x0, x0, x8 777; CHECK-NEXT: ret 778 %nega = sub i64 64, %a 779 %negb = sub i64 64, %b 780 %negasubnegb = add i64 %nega, %negb 781 %shifted = lshr i64 %val, %negasubnegb 782 ret i64 %shifted 783} 784 785;==============================================================================; 786; and patterns with an actual negation+addition 787 788define i32 @reg32_lshr_by_negated_unfolded(i32 %val, i32 %shamt) nounwind { 789; CHECK-LABEL: reg32_lshr_by_negated_unfolded: 790; CHECK: // %bb.0: 791; CHECK-NEXT: neg w8, w1 792; CHECK-NEXT: lsr w0, w0, w8 793; CHECK-NEXT: ret 794 %negshamt = sub i32 0, %shamt 795 %negaaddbitwidth = add i32 %negshamt, 32 796 %shifted = lshr i32 %val, %negaaddbitwidth 797 ret i32 %shifted 798} 799define i64 @reg64_lshr_by_negated_unfolded(i64 %val, i64 %shamt) nounwind { 800; CHECK-LABEL: reg64_lshr_by_negated_unfolded: 801; CHECK: // %bb.0: 802; CHECK-NEXT: neg x8, x1 803; CHECK-NEXT: lsr x0, x0, x8 804; CHECK-NEXT: ret 805 %negshamt = sub i64 0, %shamt 806 %negaaddbitwidth = add i64 %negshamt, 64 807 %shifted = lshr i64 %val, %negaaddbitwidth 808 ret i64 %shifted 809} 810 811define i32 @reg32_lshr_by_negated_unfolded_sub_b(i32 %val, i32 %a, i32 %b) nounwind { 812; CHECK-LABEL: reg32_lshr_by_negated_unfolded_sub_b: 813; CHECK: // %bb.0: 814; CHECK-NEXT: add w8, w1, w2 815; CHECK-NEXT: neg w8, w8 816; CHECK-NEXT: lsr w0, w0, w8 817; CHECK-NEXT: ret 818 %nega = sub i32 0, %a 819 %negaaddbitwidth = add i32 %nega, 32 820 %negaaddbitwidthsubb = sub i32 %negaaddbitwidth, %b 821 %shifted = lshr i32 %val, %negaaddbitwidthsubb 822 ret i32 %shifted 823} 824define i64 @reg64_lshr_by_negated_unfolded_sub_b(i64 %val, i64 %a, i64 %b) nounwind { 825; CHECK-LABEL: reg64_lshr_by_negated_unfolded_sub_b: 826; CHECK: // %bb.0: 827; CHECK-NEXT: add x8, x1, x2 828; CHECK-NEXT: neg x8, x8 829; CHECK-NEXT: lsr x0, x0, x8 830; CHECK-NEXT: ret 831 %nega = sub i64 0, %a 832 %negaaddbitwidth = add i64 %nega, 64 833 %negaaddbitwidthsubb = sub i64 %negaaddbitwidth, %b 834 %shifted = lshr i64 %val, %negaaddbitwidthsubb 835 ret i64 %shifted 836} 837 838define i32 @reg32_lshr_by_b_sub_negated_unfolded(i32 %val, i32 %a, i32 %b) nounwind { 839; CHECK-LABEL: reg32_lshr_by_b_sub_negated_unfolded: 840; CHECK: // %bb.0: 841; CHECK-NEXT: add w8, w2, w1 842; CHECK-NEXT: lsr w0, w0, w8 843; CHECK-NEXT: ret 844 %nega = sub i32 0, %a 845 %negaaddbitwidth = add i32 %nega, 32 846 %negaaddbitwidthsubb = sub i32 %b, %negaaddbitwidth 847 %shifted = lshr i32 %val, %negaaddbitwidthsubb 848 ret i32 %shifted 849} 850define i64 @reg64_lshr_by_b_sub_negated_unfolded(i64 %val, i64 %a, i64 %b) nounwind { 851; CHECK-LABEL: reg64_lshr_by_b_sub_negated_unfolded: 852; CHECK: // %bb.0: 853; CHECK-NEXT: add x8, x2, x1 854; CHECK-NEXT: lsr x0, x0, x8 855; CHECK-NEXT: ret 856 %nega = sub i64 0, %a 857 %negaaddbitwidth = add i64 %nega, 64 858 %negaaddbitwidthsubb = sub i64 %b, %negaaddbitwidth 859 %shifted = lshr i64 %val, %negaaddbitwidthsubb 860 ret i64 %shifted 861} 862 863define i32 @reg32_lshr_by_negated_unfolded_add_b(i32 %val, i32 %a, i32 %b) nounwind { 864; CHECK-LABEL: reg32_lshr_by_negated_unfolded_add_b: 865; CHECK: // %bb.0: 866; CHECK-NEXT: sub w8, w2, w1 867; CHECK-NEXT: lsr w0, w0, w8 868; CHECK-NEXT: ret 869 %nega = sub i32 0, %a 870 %negaaddbitwidth = add i32 %nega, 32 871 %negaaddbitwidthaddb = add i32 %negaaddbitwidth, %b 872 %shifted = lshr i32 %val, %negaaddbitwidthaddb 873 ret i32 %shifted 874} 875define i64 @reg64_lshr_by_negated_unfolded_add_b(i64 %val, i64 %a, i64 %b) nounwind { 876; CHECK-LABEL: reg64_lshr_by_negated_unfolded_add_b: 877; CHECK: // %bb.0: 878; CHECK-NEXT: sub x8, x2, x1 879; CHECK-NEXT: lsr x0, x0, x8 880; CHECK-NEXT: ret 881 %nega = sub i64 0, %a 882 %negaaddbitwidth = add i64 %nega, 64 883 %negaaddbitwidthaddb = add i64 %negaaddbitwidth, %b 884 %shifted = lshr i64 %val, %negaaddbitwidthaddb 885 ret i64 %shifted 886} 887 888;==============================================================================; 889; and patterns with an actual negation+mask 890 891define i32 @reg32_lshr_by_masked_negated_unfolded(i32 %val, i32 %shamt) nounwind { 892; CHECK-LABEL: reg32_lshr_by_masked_negated_unfolded: 893; CHECK: // %bb.0: 894; CHECK-NEXT: neg w8, w1 895; CHECK-NEXT: lsr w0, w0, w8 896; CHECK-NEXT: ret 897 %negshamt = sub i32 0, %shamt 898 %negaaddbitwidth = and i32 %negshamt, 31 899 %shifted = lshr i32 %val, %negaaddbitwidth 900 ret i32 %shifted 901} 902define i64 @reg64_lshr_by_masked_negated_unfolded(i64 %val, i64 %shamt) nounwind { 903; CHECK-LABEL: reg64_lshr_by_masked_negated_unfolded: 904; CHECK: // %bb.0: 905; CHECK-NEXT: neg w8, w1 906; CHECK-NEXT: lsr x0, x0, x8 907; CHECK-NEXT: ret 908 %negshamt = sub i64 0, %shamt 909 %negaaddbitwidth = and i64 %negshamt, 63 910 %shifted = lshr i64 %val, %negaaddbitwidth 911 ret i64 %shifted 912} 913 914define i32 @reg32_lshr_by_masked_negated_unfolded_sub_b(i32 %val, i32 %a, i32 %b) nounwind { 915; CHECK-LABEL: reg32_lshr_by_masked_negated_unfolded_sub_b: 916; CHECK: // %bb.0: 917; CHECK-NEXT: neg w8, w1 918; CHECK-NEXT: and w8, w8, #0x1f 919; CHECK-NEXT: sub w8, w8, w2 920; CHECK-NEXT: lsr w0, w0, w8 921; CHECK-NEXT: ret 922 %nega = sub i32 0, %a 923 %negaaddbitwidth = and i32 %nega, 31 924 %negaaddbitwidthsubb = sub i32 %negaaddbitwidth, %b 925 %shifted = lshr i32 %val, %negaaddbitwidthsubb 926 ret i32 %shifted 927} 928define i64 @reg64_lshr_by_masked_negated_unfolded_sub_b(i64 %val, i64 %a, i64 %b) nounwind { 929; CHECK-LABEL: reg64_lshr_by_masked_negated_unfolded_sub_b: 930; CHECK: // %bb.0: 931; CHECK-NEXT: neg w8, w1 932; CHECK-NEXT: and x8, x8, #0x3f 933; CHECK-NEXT: sub x8, x8, x2 934; CHECK-NEXT: lsr x0, x0, x8 935; CHECK-NEXT: ret 936 %nega = sub i64 0, %a 937 %negaaddbitwidth = and i64 %nega, 63 938 %negaaddbitwidthsubb = sub i64 %negaaddbitwidth, %b 939 %shifted = lshr i64 %val, %negaaddbitwidthsubb 940 ret i64 %shifted 941} 942 943define i32 @reg32_lshr_by_masked_b_sub_negated_unfolded(i32 %val, i32 %a, i32 %b) nounwind { 944; CHECK-LABEL: reg32_lshr_by_masked_b_sub_negated_unfolded: 945; CHECK: // %bb.0: 946; CHECK-NEXT: neg w8, w1 947; CHECK-NEXT: and w8, w8, #0x1f 948; CHECK-NEXT: sub w8, w2, w8 949; CHECK-NEXT: lsr w0, w0, w8 950; CHECK-NEXT: ret 951 %nega = sub i32 0, %a 952 %negaaddbitwidth = and i32 %nega, 31 953 %negaaddbitwidthsubb = sub i32 %b, %negaaddbitwidth 954 %shifted = lshr i32 %val, %negaaddbitwidthsubb 955 ret i32 %shifted 956} 957define i64 @reg64_lshr_by_masked_b_sub_negated_unfolded(i64 %val, i64 %a, i64 %b) nounwind { 958; CHECK-LABEL: reg64_lshr_by_masked_b_sub_negated_unfolded: 959; CHECK: // %bb.0: 960; CHECK-NEXT: neg w8, w1 961; CHECK-NEXT: and x8, x8, #0x3f 962; CHECK-NEXT: sub x8, x2, x8 963; CHECK-NEXT: lsr x0, x0, x8 964; CHECK-NEXT: ret 965 %nega = sub i64 0, %a 966 %negaaddbitwidth = and i64 %nega, 63 967 %negaaddbitwidthsubb = sub i64 %b, %negaaddbitwidth 968 %shifted = lshr i64 %val, %negaaddbitwidthsubb 969 ret i64 %shifted 970} 971 972define i32 @reg32_lshr_by_masked_negated_unfolded_add_b(i32 %val, i32 %a, i32 %b) nounwind { 973; CHECK-LABEL: reg32_lshr_by_masked_negated_unfolded_add_b: 974; CHECK: // %bb.0: 975; CHECK-NEXT: neg w8, w1 976; CHECK-NEXT: and w8, w8, #0x1f 977; CHECK-NEXT: add w8, w8, w2 978; CHECK-NEXT: lsr w0, w0, w8 979; CHECK-NEXT: ret 980 %nega = sub i32 0, %a 981 %negaaddbitwidth = and i32 %nega, 31 982 %negaaddbitwidthaddb = add i32 %negaaddbitwidth, %b 983 %shifted = lshr i32 %val, %negaaddbitwidthaddb 984 ret i32 %shifted 985} 986define i64 @reg64_lshr_by_masked_negated_unfolded_add_b(i64 %val, i64 %a, i64 %b) nounwind { 987; CHECK-LABEL: reg64_lshr_by_masked_negated_unfolded_add_b: 988; CHECK: // %bb.0: 989; CHECK-NEXT: neg w8, w1 990; CHECK-NEXT: and x8, x8, #0x3f 991; CHECK-NEXT: add x8, x8, x2 992; CHECK-NEXT: lsr x0, x0, x8 993; CHECK-NEXT: ret 994 %nega = sub i64 0, %a 995 %negaaddbitwidth = and i64 %nega, 63 996 %negaaddbitwidthaddb = add i64 %negaaddbitwidth, %b 997 %shifted = lshr i64 %val, %negaaddbitwidthaddb 998 ret i64 %shifted 999} 1000 1001define i32 @t(i64 %x) { 1002; CHECK-LABEL: t: 1003; CHECK: // %bb.0: 1004; CHECK-NEXT: ubfx x0, x0, #17, #28 1005; CHECK-NEXT: // kill: def $w0 killed $w0 killed $x0 1006; CHECK-NEXT: ret 1007 %s = lshr i64 %x, 13 1008 %t = trunc i64 %s to i32 1009 %r = lshr i32 %t, 4 1010 ret i32 %r 1011} 1012