1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-linux-gnu -verify-machineinstrs | FileCheck %s 3 4; Note that this should be refactored (for efficiency if nothing else) 5; when the PCS is implemented so we don't have to worry about the 6; loads and stores. 7 8@var_i32 = global i32 42 9@var2_i32 = global i32 43 10@var_i64 = global i64 0 11 12; Add pure 12-bit immediates: 13define void @add_small() { 14; CHECK-LABEL: add_small: 15; CHECK: // %bb.0: 16; CHECK-NEXT: adrp x8, :got:var_i32 17; CHECK-NEXT: adrp x9, :got:var_i64 18; CHECK-NEXT: ldr x8, [x8, :got_lo12:var_i32] 19; CHECK-NEXT: ldr x9, [x9, :got_lo12:var_i64] 20; CHECK-NEXT: ldr w10, [x8] 21; CHECK-NEXT: ldr x11, [x9] 22; CHECK-NEXT: add w10, w10, #4095 23; CHECK-NEXT: add x11, x11, #52 24; CHECK-NEXT: str w10, [x8] 25; CHECK-NEXT: str x11, [x9] 26; CHECK-NEXT: ret 27 28 %val32 = load i32, ptr @var_i32 29 %newval32 = add i32 %val32, 4095 30 store i32 %newval32, ptr @var_i32 31 32 %val64 = load i64, ptr @var_i64 33 %newval64 = add i64 %val64, 52 34 store i64 %newval64, ptr @var_i64 35 36 ret void 37} 38 39; Make sure we grab the imm variant when the register operand 40; can be implicitly zero-extend. 41; We used to generate something horrible like this: 42; wA = ldrb 43; xB = ldimm 12 44; xC = add xB, wA, uxtb 45; whereas this can be achieved with: 46; wA = ldrb 47; xC = add xA, #12 ; <- xA implicitly zero extend wA. 48define void @add_small_imm(ptr %p, ptr %q, i32 %b, ptr %addr) { 49; CHECK-LABEL: add_small_imm: 50; CHECK: // %bb.0: // %entry 51; CHECK-NEXT: ldrb w8, [x0] 52; CHECK-NEXT: add w9, w8, w2 53; CHECK-NEXT: add x8, x8, #12 54; CHECK-NEXT: str w9, [x3] 55; CHECK-NEXT: str x8, [x1] 56; CHECK-NEXT: ret 57entry: 58 59 %t = load i8, ptr %p 60 %promoted = zext i8 %t to i64 61 %zextt = zext i8 %t to i32 62 %add = add nuw i32 %zextt, %b 63 64 %add2 = add nuw i64 %promoted, 12 65 store i32 %add, ptr %addr 66 67 store i64 %add2, ptr %q 68 ret void 69} 70 71; Add 12-bit immediates, shifted left by 12 bits 72define void @add_med() { 73; CHECK-LABEL: add_med: 74; CHECK: // %bb.0: 75; CHECK-NEXT: adrp x8, :got:var_i32 76; CHECK-NEXT: adrp x9, :got:var_i64 77; CHECK-NEXT: ldr x8, [x8, :got_lo12:var_i32] 78; CHECK-NEXT: ldr x9, [x9, :got_lo12:var_i64] 79; CHECK-NEXT: ldr w10, [x8] 80; CHECK-NEXT: ldr x11, [x9] 81; CHECK-NEXT: add w10, w10, #3567, lsl #12 // =14610432 82; CHECK-NEXT: add x11, x11, #4095, lsl #12 // =16773120 83; CHECK-NEXT: str w10, [x8] 84; CHECK-NEXT: str x11, [x9] 85; CHECK-NEXT: ret 86 87 %val32 = load i32, ptr @var_i32 88 %newval32 = add i32 %val32, 14610432 ; =0xdef000 89 store i32 %newval32, ptr @var_i32 90 91 %val64 = load i64, ptr @var_i64 92 %newval64 = add i64 %val64, 16773120 ; =0xfff000 93 store i64 %newval64, ptr @var_i64 94 95 ret void 96} 97 98; Subtract 12-bit immediates 99define void @sub_small() { 100; CHECK-LABEL: sub_small: 101; CHECK: // %bb.0: 102; CHECK-NEXT: adrp x8, :got:var_i32 103; CHECK-NEXT: adrp x9, :got:var_i64 104; CHECK-NEXT: ldr x8, [x8, :got_lo12:var_i32] 105; CHECK-NEXT: ldr x9, [x9, :got_lo12:var_i64] 106; CHECK-NEXT: ldr w10, [x8] 107; CHECK-NEXT: ldr x11, [x9] 108; CHECK-NEXT: sub w10, w10, #4095 109; CHECK-NEXT: sub x11, x11, #52 110; CHECK-NEXT: str w10, [x8] 111; CHECK-NEXT: str x11, [x9] 112; CHECK-NEXT: ret 113 114 %val32 = load i32, ptr @var_i32 115 %newval32 = sub i32 %val32, 4095 116 store i32 %newval32, ptr @var_i32 117 118 %val64 = load i64, ptr @var_i64 119 %newval64 = sub i64 %val64, 52 120 store i64 %newval64, ptr @var_i64 121 122 ret void 123} 124 125; Subtract 12-bit immediates, shifted left by 12 bits 126define void @sub_med() { 127; CHECK-LABEL: sub_med: 128; CHECK: // %bb.0: 129; CHECK-NEXT: adrp x8, :got:var_i32 130; CHECK-NEXT: adrp x9, :got:var_i64 131; CHECK-NEXT: ldr x8, [x8, :got_lo12:var_i32] 132; CHECK-NEXT: ldr x9, [x9, :got_lo12:var_i64] 133; CHECK-NEXT: ldr w10, [x8] 134; CHECK-NEXT: ldr x11, [x9] 135; CHECK-NEXT: sub w10, w10, #3567, lsl #12 // =14610432 136; CHECK-NEXT: sub x11, x11, #4095, lsl #12 // =16773120 137; CHECK-NEXT: str w10, [x8] 138; CHECK-NEXT: str x11, [x9] 139; CHECK-NEXT: ret 140 141 %val32 = load i32, ptr @var_i32 142 %newval32 = sub i32 %val32, 14610432 ; =0xdef000 143 store i32 %newval32, ptr @var_i32 144 145 %val64 = load i64, ptr @var_i64 146 %newval64 = sub i64 %val64, 16773120 ; =0xfff000 147 store i64 %newval64, ptr @var_i64 148 149 ret void 150} 151 152define i64 @add_two_parts_imm_i64(i64 %a) { 153; CHECK-LABEL: add_two_parts_imm_i64: 154; CHECK: // %bb.0: 155; CHECK-NEXT: add x8, x0, #2730, lsl #12 // =11182080 156; CHECK-NEXT: add x0, x8, #1365 157; CHECK-NEXT: ret 158 %b = add i64 %a, 11183445 159 ret i64 %b 160} 161 162define i32 @add_two_parts_imm_i32(i32 %a) { 163; CHECK-LABEL: add_two_parts_imm_i32: 164; CHECK: // %bb.0: 165; CHECK-NEXT: add w8, w0, #2730, lsl #12 // =11182080 166; CHECK-NEXT: add w0, w8, #1365 167; CHECK-NEXT: ret 168 %b = add i32 %a, 11183445 169 ret i32 %b 170} 171 172define i64 @add_two_parts_imm_i64_neg(i64 %a) { 173; CHECK-LABEL: add_two_parts_imm_i64_neg: 174; CHECK: // %bb.0: 175; CHECK-NEXT: sub x8, x0, #2730, lsl #12 // =11182080 176; CHECK-NEXT: sub x0, x8, #1365 177; CHECK-NEXT: ret 178 %b = add i64 %a, -11183445 179 ret i64 %b 180} 181 182define i32 @add_two_parts_imm_i32_neg(i32 %a) { 183; CHECK-LABEL: add_two_parts_imm_i32_neg: 184; CHECK: // %bb.0: 185; CHECK-NEXT: sub w8, w0, #2730, lsl #12 // =11182080 186; CHECK-NEXT: sub w0, w8, #1365 187; CHECK-NEXT: ret 188 %b = add i32 %a, -11183445 189 ret i32 %b 190} 191 192define i64 @sub_two_parts_imm_i64(i64 %a) { 193; CHECK-LABEL: sub_two_parts_imm_i64: 194; CHECK: // %bb.0: 195; CHECK-NEXT: sub x8, x0, #2730, lsl #12 // =11182080 196; CHECK-NEXT: sub x0, x8, #1365 197; CHECK-NEXT: ret 198 %b = sub i64 %a, 11183445 199 ret i64 %b 200} 201 202define i32 @sub_two_parts_imm_i32(i32 %a) { 203; CHECK-LABEL: sub_two_parts_imm_i32: 204; CHECK: // %bb.0: 205; CHECK-NEXT: sub w8, w0, #2730, lsl #12 // =11182080 206; CHECK-NEXT: sub w0, w8, #1365 207; CHECK-NEXT: ret 208 %b = sub i32 %a, 11183445 209 ret i32 %b 210} 211 212define i64 @sub_two_parts_imm_i64_neg(i64 %a) { 213; CHECK-LABEL: sub_two_parts_imm_i64_neg: 214; CHECK: // %bb.0: 215; CHECK-NEXT: add x8, x0, #2730, lsl #12 // =11182080 216; CHECK-NEXT: add x0, x8, #1365 217; CHECK-NEXT: ret 218 %b = sub i64 %a, -11183445 219 ret i64 %b 220} 221 222define i32 @sub_two_parts_imm_i32_neg(i32 %a) { 223; CHECK-LABEL: sub_two_parts_imm_i32_neg: 224; CHECK: // %bb.0: 225; CHECK-NEXT: add w8, w0, #2730, lsl #12 // =11182080 226; CHECK-NEXT: add w0, w8, #1365 227; CHECK-NEXT: ret 228 %b = sub i32 %a, -11183445 229 ret i32 %b 230} 231 232define i32 @add_27962026(i32 %a) { 233; CHECK-LABEL: add_27962026: 234; CHECK: // %bb.0: 235; CHECK-NEXT: mov w8, #43690 // =0xaaaa 236; CHECK-NEXT: movk w8, #426, lsl #16 237; CHECK-NEXT: add w0, w0, w8 238; CHECK-NEXT: ret 239 %b = add i32 %a, 27962026 240 ret i32 %b 241} 242 243define i32 @add_65534(i32 %a) { 244; CHECK-LABEL: add_65534: 245; CHECK: // %bb.0: 246; CHECK-NEXT: mov w8, #65534 // =0xfffe 247; CHECK-NEXT: add w0, w0, w8 248; CHECK-NEXT: ret 249 %b = add i32 %a, 65534 250 ret i32 %b 251} 252 253declare i32 @foox(i32) 254 255define void @add_in_loop(i32 %0) { 256; CHECK-LABEL: add_in_loop: 257; CHECK: // %bb.0: 258; CHECK-NEXT: stp x30, x19, [sp, #-16]! // 16-byte Folded Spill 259; CHECK-NEXT: .cfi_def_cfa_offset 16 260; CHECK-NEXT: .cfi_offset w19, -8 261; CHECK-NEXT: .cfi_offset w30, -16 262; CHECK-NEXT: mov w19, #43690 // =0xaaaa 263; CHECK-NEXT: movk w19, #170, lsl #16 264; CHECK-NEXT: .LBB15_1: // =>This Inner Loop Header: Depth=1 265; CHECK-NEXT: add w0, w0, w19 266; CHECK-NEXT: bl foox 267; CHECK-NEXT: b .LBB15_1 268 br label %2 2692: 270 %3 = phi i32 [ %0, %1 ], [ %5, %2 ] 271 %4 = add nsw i32 %3, 11184810 272 %5 = tail call i32 @foox(i32 %4) #2 273 br label %2 274} 275 276define void @testing() { 277; CHECK-LABEL: testing: 278; CHECK: // %bb.0: 279; CHECK-NEXT: adrp x8, :got:var_i32 280; CHECK-NEXT: ldr x8, [x8, :got_lo12:var_i32] 281; CHECK-NEXT: ldr w9, [x8] 282; CHECK-NEXT: cmp w9, #4095 283; CHECK-NEXT: b.ne .LBB16_6 284; CHECK-NEXT: // %bb.1: // %test2 285; CHECK-NEXT: adrp x10, :got:var2_i32 286; CHECK-NEXT: add w11, w9, #1 287; CHECK-NEXT: ldr x10, [x10, :got_lo12:var2_i32] 288; CHECK-NEXT: str w11, [x8] 289; CHECK-NEXT: ldr w10, [x10] 290; CHECK-NEXT: cmp w10, #3567, lsl #12 // =14610432 291; CHECK-NEXT: b.lo .LBB16_6 292; CHECK-NEXT: // %bb.2: // %test3 293; CHECK-NEXT: add w11, w9, #2 294; CHECK-NEXT: cmp w9, #123 295; CHECK-NEXT: str w11, [x8] 296; CHECK-NEXT: b.lt .LBB16_6 297; CHECK-NEXT: // %bb.3: // %test4 298; CHECK-NEXT: add w11, w9, #3 299; CHECK-NEXT: cmp w10, #321 300; CHECK-NEXT: str w11, [x8] 301; CHECK-NEXT: b.gt .LBB16_6 302; CHECK-NEXT: // %bb.4: // %test5 303; CHECK-NEXT: add w11, w9, #4 304; CHECK-NEXT: cmn w10, #443 305; CHECK-NEXT: str w11, [x8] 306; CHECK-NEXT: b.ge .LBB16_6 307; CHECK-NEXT: // %bb.5: // %test6 308; CHECK-NEXT: add w9, w9, #5 309; CHECK-NEXT: str w9, [x8] 310; CHECK-NEXT: .LBB16_6: // %common.ret 311; CHECK-NEXT: ret 312 %val = load i32, ptr @var_i32 313 %val2 = load i32, ptr @var2_i32 314 315 %cmp_pos_small = icmp ne i32 %val, 4095 316 br i1 %cmp_pos_small, label %ret, label %test2 317 318test2: 319 %newval2 = add i32 %val, 1 320 store i32 %newval2, ptr @var_i32 321 %cmp_pos_big = icmp ult i32 %val2, 14610432 322 br i1 %cmp_pos_big, label %ret, label %test3 323 324test3: 325 %newval3 = add i32 %val, 2 326 store i32 %newval3, ptr @var_i32 327 %cmp_pos_slt = icmp slt i32 %val, 123 328 br i1 %cmp_pos_slt, label %ret, label %test4 329 330test4: 331 %newval4 = add i32 %val, 3 332 store i32 %newval4, ptr @var_i32 333 %cmp_pos_sgt = icmp sgt i32 %val2, 321 334 br i1 %cmp_pos_sgt, label %ret, label %test5 335 336test5: 337 %newval5 = add i32 %val, 4 338 store i32 %newval5, ptr @var_i32 339 %cmp_neg_uge = icmp sgt i32 %val2, -444 340 br i1 %cmp_neg_uge, label %ret, label %test6 341 342test6: 343 %newval6 = add i32 %val, 5 344 store i32 %newval6, ptr @var_i32 345 ret void 346 347ret: 348 ret void 349} 350 351declare {i32, i1} @llvm.sadd.with.overflow.i32(i32 %a, i32 %b) 352 353define i1 @sadd_add(i32 %a, i32 %b, ptr %p) { 354; CHECK-LABEL: sadd_add: 355; CHECK: // %bb.0: 356; CHECK-NEXT: mvn w8, w0 357; CHECK-NEXT: adds w8, w8, w1 358; CHECK-NEXT: cset w0, vs 359; CHECK-NEXT: add w8, w8, #1 360; CHECK-NEXT: str w8, [x2] 361; CHECK-NEXT: ret 362 %nota = xor i32 %a, -1 363 %a0 = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %nota, i32 %b) 364 %e0 = extractvalue {i32, i1} %a0, 0 365 %e1 = extractvalue {i32, i1} %a0, 1 366 %res = add i32 %e0, 1 367 store i32 %res, ptr %p 368 ret i1 %e1 369} 370 371declare {i8, i1} @llvm.uadd.with.overflow.i8(i8 %a, i8 %b) 372 373define i1 @uadd_add(i8 %a, i8 %b, ptr %p) { 374; CHECK-LABEL: uadd_add: 375; CHECK: // %bb.0: 376; CHECK-NEXT: mov w8, #255 // =0xff 377; CHECK-NEXT: bic w8, w8, w0 378; CHECK-NEXT: add w8, w8, w1, uxtb 379; CHECK-NEXT: lsr w0, w8, #8 380; CHECK-NEXT: add w8, w8, #1 381; CHECK-NEXT: strb w8, [x2] 382; CHECK-NEXT: ret 383 %nota = xor i8 %a, -1 384 %a0 = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 %nota, i8 %b) 385 %e0 = extractvalue {i8, i1} %a0, 0 386 %e1 = extractvalue {i8, i1} %a0, 1 387 %res = add i8 %e0, 1 388 store i8 %res, ptr %p 389 ret i1 %e1 390} 391 392; This is a unique edge case that will generate the following MIR 393; MOVi32imm -1000000 394; SUBREG_TO_REG 0, killed %1, %subreg.sub_32 395; When using a 64-bit unsigned for the "-1000000" immediate, the code 396; must make sure to zero out the top 32 bits since SUBREG_TO_REG is 397; zero extending the value 398define i64 @addl_0x80000000(i64 %a) { 399; CHECK-LABEL: addl_0x80000000: 400; CHECK: // %bb.0: 401; CHECK-NEXT: mov w8, #48576 // =0xbdc0 402; CHECK-NEXT: movk w8, #65520, lsl #16 403; CHECK-NEXT: add x0, x0, x8 404; CHECK-NEXT: ret 405 %b = add i64 %a, 4293967296 406 ret i64 %b 407} 408 409; ADDS and SUBS Optimizations 410; Checks with all types first, then checks that only EQ and NE optimize 411define i1 @eq_i(i32 %0) { 412; CHECK-LABEL: eq_i: 413; CHECK: // %bb.0: 414; CHECK-NEXT: sub w8, w0, #273, lsl #12 // =1118208 415; CHECK-NEXT: cmp w8, #273 416; CHECK-NEXT: cset w0, eq 417; CHECK-NEXT: ret 418 %2 = icmp eq i32 %0, 1118481 419 ret i1 %2 420} 421 422define i1 @eq_l(i64 %0) { 423; CHECK-LABEL: eq_l: 424; CHECK: // %bb.0: 425; CHECK-NEXT: sub x8, x0, #273, lsl #12 // =1118208 426; CHECK-NEXT: cmp x8, #273 427; CHECK-NEXT: cset w0, eq 428; CHECK-NEXT: ret 429 %2 = icmp eq i64 %0, 1118481 430 ret i1 %2 431} 432 433define i1 @ne_i(i32 %0) { 434; CHECK-LABEL: ne_i: 435; CHECK: // %bb.0: 436; CHECK-NEXT: sub w8, w0, #273, lsl #12 // =1118208 437; CHECK-NEXT: cmp w8, #273 438; CHECK-NEXT: cset w0, ne 439; CHECK-NEXT: ret 440 %2 = icmp ne i32 %0, 1118481 441 ret i1 %2 442} 443 444define i1 @ne_l(i64 %0) { 445; CHECK-LABEL: ne_l: 446; CHECK: // %bb.0: 447; CHECK-NEXT: sub x8, x0, #273, lsl #12 // =1118208 448; CHECK-NEXT: cmp x8, #273 449; CHECK-NEXT: cset w0, ne 450; CHECK-NEXT: ret 451 %2 = icmp ne i64 %0, 1118481 452 ret i1 %2 453} 454 455define i1 @eq_in(i32 %0) { 456; CHECK-LABEL: eq_in: 457; CHECK: // %bb.0: 458; CHECK-NEXT: add w8, w0, #273, lsl #12 // =1118208 459; CHECK-NEXT: cmn w8, #273 460; CHECK-NEXT: cset w0, eq 461; CHECK-NEXT: ret 462 %2 = icmp eq i32 %0, -1118481 463 ret i1 %2 464} 465 466define i1 @eq_ln(i64 %0) { 467; CHECK-LABEL: eq_ln: 468; CHECK: // %bb.0: 469; CHECK-NEXT: add x8, x0, #273, lsl #12 // =1118208 470; CHECK-NEXT: cmn x8, #273 471; CHECK-NEXT: cset w0, eq 472; CHECK-NEXT: ret 473 %2 = icmp eq i64 %0, -1118481 474 ret i1 %2 475} 476 477define i1 @ne_in(i32 %0) { 478; CHECK-LABEL: ne_in: 479; CHECK: // %bb.0: 480; CHECK-NEXT: add w8, w0, #273, lsl #12 // =1118208 481; CHECK-NEXT: cmn w8, #273 482; CHECK-NEXT: cset w0, ne 483; CHECK-NEXT: ret 484 %2 = icmp ne i32 %0, -1118481 485 ret i1 %2 486} 487 488define i1 @ne_ln(i64 %0) { 489; CHECK-LABEL: ne_ln: 490; CHECK: // %bb.0: 491; CHECK-NEXT: add x8, x0, #273, lsl #12 // =1118208 492; CHECK-NEXT: cmn x8, #273 493; CHECK-NEXT: cset w0, ne 494; CHECK-NEXT: ret 495 %2 = icmp ne i64 %0, -1118481 496 ret i1 %2 497} 498 499define i1 @reject_eq(i32 %0) { 500; CHECK-LABEL: reject_eq: 501; CHECK: // %bb.0: 502; CHECK-NEXT: mov w8, #51712 // =0xca00 503; CHECK-NEXT: movk w8, #15258, lsl #16 504; CHECK-NEXT: cmp w0, w8 505; CHECK-NEXT: cset w0, eq 506; CHECK-NEXT: ret 507 %2 = icmp eq i32 %0, 1000000000 508 ret i1 %2 509} 510 511define i1 @reject_non_eqne_csinc(i32 %0) { 512; CHECK-LABEL: reject_non_eqne_csinc: 513; CHECK: // %bb.0: 514; CHECK-NEXT: mov w8, #4369 // =0x1111 515; CHECK-NEXT: movk w8, #17, lsl #16 516; CHECK-NEXT: cmp w0, w8 517; CHECK-NEXT: cset w0, lo 518; CHECK-NEXT: ret 519 %2 = icmp ult i32 %0, 1118481 520 ret i1 %2 521} 522 523define i32 @accept_csel(i32 %0) { 524; CHECK-LABEL: accept_csel: 525; CHECK: // %bb.0: 526; CHECK-NEXT: sub w9, w0, #273, lsl #12 // =1118208 527; CHECK-NEXT: mov w8, #17 // =0x11 528; CHECK-NEXT: cmp w9, #273 529; CHECK-NEXT: mov w9, #11 // =0xb 530; CHECK-NEXT: csel w0, w9, w8, eq 531; CHECK-NEXT: ret 532 %2 = icmp eq i32 %0, 1118481 533 %3 = select i1 %2, i32 11, i32 17 534 ret i32 %3 535} 536 537define i32 @reject_non_eqne_csel(i32 %0) { 538; CHECK-LABEL: reject_non_eqne_csel: 539; CHECK: // %bb.0: 540; CHECK-NEXT: mov w8, #4369 // =0x1111 541; CHECK-NEXT: mov w9, #11 // =0xb 542; CHECK-NEXT: movk w8, #17, lsl #16 543; CHECK-NEXT: cmp w0, w8 544; CHECK-NEXT: mov w8, #17 // =0x11 545; CHECK-NEXT: csel w0, w9, w8, lo 546; CHECK-NEXT: ret 547 %2 = icmp ult i32 %0, 1118481 548 %3 = select i1 %2, i32 11, i32 17 549 ret i32 %3 550} 551 552declare void @fooy() 553 554define void @accept_branch(i32 %0) { 555; CHECK-LABEL: accept_branch: 556; CHECK: // %bb.0: 557; CHECK-NEXT: sub w8, w0, #291, lsl #12 // =1191936 558; CHECK-NEXT: cmp w8, #1110 559; CHECK-NEXT: b.eq .LBB32_2 560; CHECK-NEXT: // %bb.1: 561; CHECK-NEXT: ret 562; CHECK-NEXT: .LBB32_2: 563; CHECK-NEXT: b fooy 564 %2 = icmp ne i32 %0, 1193046 565 br i1 %2, label %4, label %3 5663: ; preds = %1 567 tail call void @fooy() 568 br label %4 5694: ; preds = %3, %1 570 ret void 571} 572 573define void @reject_non_eqne_branch(i32 %0) { 574; CHECK-LABEL: reject_non_eqne_branch: 575; CHECK: // %bb.0: 576; CHECK-NEXT: mov w8, #13398 // =0x3456 577; CHECK-NEXT: movk w8, #18, lsl #16 578; CHECK-NEXT: cmp w0, w8 579; CHECK-NEXT: b.le .LBB33_2 580; CHECK-NEXT: // %bb.1: 581; CHECK-NEXT: ret 582; CHECK-NEXT: .LBB33_2: 583; CHECK-NEXT: b fooy 584 %2 = icmp sgt i32 %0, 1193046 585 br i1 %2, label %4, label %3 5863: ; preds = %1 587 tail call void @fooy() 588 br label %4 5894: ; preds = %3, %1 590 ret void 591} 592 593define i32 @reject_multiple_usages(i32 %0) { 594; CHECK-LABEL: reject_multiple_usages: 595; CHECK: // %bb.0: 596; CHECK-NEXT: mov w8, #4369 // =0x1111 597; CHECK-NEXT: mov w9, #3 // =0x3 598; CHECK-NEXT: mov w10, #17 // =0x11 599; CHECK-NEXT: movk w8, #17, lsl #16 600; CHECK-NEXT: mov w11, #12 // =0xc 601; CHECK-NEXT: cmp w0, w8 602; CHECK-NEXT: mov w8, #9 // =0x9 603; CHECK-NEXT: csel w8, w8, w9, eq 604; CHECK-NEXT: csel w9, w11, w10, hi 605; CHECK-NEXT: mov w10, #53312 // =0xd040 606; CHECK-NEXT: movk w10, #2, lsl #16 607; CHECK-NEXT: add w8, w8, w9 608; CHECK-NEXT: mov w9, #26304 // =0x66c0 609; CHECK-NEXT: cmp w0, w10 610; CHECK-NEXT: movk w9, #1433, lsl #16 611; CHECK-NEXT: csel w0, w8, w9, hi 612; CHECK-NEXT: ret 613 %2 = icmp eq i32 %0, 1118481 614 %3 = icmp ugt i32 %0, 1118481 615 %4 = select i1 %2, i32 9, i32 3 616 %5 = select i1 %3, i32 12, i32 17 617 %6 = add i32 %4, %5 618 %7 = icmp ugt i32 %0, 184384 619 %8 = select i1 %7, i32 %6, i32 93939392 620 ret i32 %8 621} 622 623; Unique case found in ClangBuiltLinux where the DstReg is not Virtual and 624; caused an assertion failure 625define dso_local i32 @neigh_periodic_work_tbl_1() { 626; CHECK-LABEL: neigh_periodic_work_tbl_1: 627; CHECK: // %bb.0: // %entry 628; CHECK-NEXT: adrp x8, neigh_periodic_work_tbl_1 629; CHECK-NEXT: add x8, x8, :lo12:neigh_periodic_work_tbl_1 630; CHECK-NEXT: add x8, x8, #18, lsl #12 // =73728 631; CHECK-NEXT: cmn x8, #1272 632; CHECK-NEXT: b.mi .LBB35_2 633; CHECK-NEXT: // %bb.1: // %if.end 634; CHECK-NEXT: ret 635; CHECK-NEXT: .LBB35_2: // %for.cond 636; CHECK-NEXT: // =>This Inner Loop Header: Depth=1 637; CHECK-NEXT: b .LBB35_2 638entry: 639 %cmp = icmp slt i64 add (i64 ptrtoint (ptr @neigh_periodic_work_tbl_1 to i64), i64 75000), 0 640 br i1 %cmp, label %for.cond, label %if.end 641for.cond: ; preds = %entry, %for.cond 642 br label %for.cond 643if.end: ; preds = %entry 644 ret i32 undef 645} 646 647@jiffies = dso_local local_unnamed_addr global i32 0, align 4 648@primary_crng = dso_local local_unnamed_addr global i32 0, align 4 649@input_pool = dso_local global i32 0, align 4 650declare dso_local i32 @crng_reseed(...) local_unnamed_addr 651; Function Attrs: nounwind uwtable 652define dso_local i32 @_extract_crng_crng() { 653; CHECK-LABEL: _extract_crng_crng: 654; CHECK: // %bb.0: // %entry 655; CHECK-NEXT: adrp x8, _extract_crng_crng 656; CHECK-NEXT: add x8, x8, :lo12:_extract_crng_crng 657; CHECK-NEXT: tbnz x8, #63, .LBB36_2 658; CHECK-NEXT: // %bb.1: // %lor.lhs.false 659; CHECK-NEXT: adrp x9, jiffies 660; CHECK-NEXT: ldrsw x9, [x9, :lo12:jiffies] 661; CHECK-NEXT: sub x8, x8, x9 662; CHECK-NEXT: add x8, x8, #18, lsl #12 // =73728 663; CHECK-NEXT: cmn x8, #1272 664; CHECK-NEXT: b.pl .LBB36_3 665; CHECK-NEXT: .LBB36_2: // %if.then 666; CHECK-NEXT: adrp x8, primary_crng 667; CHECK-NEXT: ldr w8, [x8, :lo12:primary_crng] 668; CHECK-NEXT: cmp w8, #0 669; CHECK-NEXT: adrp x8, input_pool 670; CHECK-NEXT: add x8, x8, :lo12:input_pool 671; CHECK-NEXT: csel x0, xzr, x8, eq 672; CHECK-NEXT: b crng_reseed 673; CHECK-NEXT: .LBB36_3: // %if.end 674; CHECK-NEXT: ret 675entry: 676 %cmp2 = icmp slt ptr @_extract_crng_crng, null 677 br i1 %cmp2, label %if.then, label %lor.lhs.false 678lor.lhs.false: ; preds = %entry 679 %0 = load i32, ptr @jiffies, align 4 680 %idx.ext = sext i32 %0 to i64 681 %idx.neg = sub nsw i64 0, %idx.ext 682 %add.ptr = getelementptr i8, ptr getelementptr (i8, ptr @_extract_crng_crng, i64 75000), i64 %idx.neg 683 %cmp = icmp slt ptr %add.ptr, null 684 br i1 %cmp, label %if.then, label %if.end 685if.then: ; preds = %lor.lhs.false, %entry 686 %1 = load i32, ptr @primary_crng, align 4 687 %tobool.not = icmp eq i32 %1, 0 688 %cond = select i1 %tobool.not, ptr null, ptr @input_pool 689 %call = tail call i32 @crng_reseed(ptr noundef %cond) 690 br label %if.end 691if.end: ; preds = %if.then, %lor.lhs.false 692 ret i32 undef 693} 694 695; ((X << C) - Y) + Z --> (Z - Y) + (X << C) 696define i32 @commute_subop0(i32 %x, i32 %y, i32 %z) { 697; CHECK-LABEL: commute_subop0: 698; CHECK: // %bb.0: 699; CHECK-NEXT: sub w8, w2, w1 700; CHECK-NEXT: add w0, w8, w0, lsl #3 701; CHECK-NEXT: ret 702 %shl = shl i32 %x, 3 703 %sub = sub i32 %shl, %y 704 %add = add i32 %sub, %z 705 ret i32 %add 706} 707 708; ((X >> C) - Y) + Z --> (Z - Y) + (X >> C) 709define i32 @commute_subop0_lshr(i32 %x, i32 %y, i32 %z) { 710; CHECK-LABEL: commute_subop0_lshr: 711; CHECK: // %bb.0: 712; CHECK-NEXT: sub w8, w2, w1 713; CHECK-NEXT: add w0, w8, w0, lsr #3 714; CHECK-NEXT: ret 715 %lshr = lshr i32 %x, 3 716 %sub = sub i32 %lshr, %y 717 %add = add i32 %sub, %z 718 ret i32 %add 719} 720 721; ((X >> C) - Y) + Z --> (Z - Y) + (X >> C) 722define i32 @commute_subop0_ashr(i32 %x, i32 %y, i32 %z) { 723; CHECK-LABEL: commute_subop0_ashr: 724; CHECK: // %bb.0: 725; CHECK-NEXT: sub w8, w2, w1 726; CHECK-NEXT: add w0, w8, w0, asr #3 727; CHECK-NEXT: ret 728 %ashr = ashr i32 %x, 3 729 %sub = sub i32 %ashr, %y 730 %add = add i32 %sub, %z 731 ret i32 %add 732} 733 734; ((sext X) - Y) + Z --> (Z - Y) + (sext X) 735define i64 @commute_subop0_sext(i32 %x, i64 %y, i64 %z) { 736; CHECK-LABEL: commute_subop0_sext: 737; CHECK: // %bb.0: 738; CHECK-NEXT: sub x8, x2, x1 739; CHECK-NEXT: add x0, x8, w0, sxtw 740; CHECK-NEXT: ret 741 %sext = sext i32 %x to i64 742 %sub = sub i64 %sext, %y 743 %add = add i64 %sub, %z 744 ret i64 %add 745} 746 747; ((sext_inreg X) - Y) + Z --> (Z - Y) + (sext_inreg X) 748define i64 @commute_subop0_sext_inreg(i64 %x, i64 %y, i64 %z) { 749; CHECK-LABEL: commute_subop0_sext_inreg: 750; CHECK: // %bb.0: 751; CHECK-NEXT: sub x8, x2, x1 752; CHECK-NEXT: add x0, x8, w0, sxth 753; CHECK-NEXT: ret 754 %shl = shl i64 %x, 48 755 %ashr = ashr i64 %shl, 48 756 %sub = sub i64 %ashr, %y 757 %add = add i64 %sub, %z 758 ret i64 %add 759} 760 761; ((zext X) - Y) + Z --> (Z - Y) + (zext X) 762define i32 @commute_subop0_zext(i16 %x, i32 %y, i32 %z) { 763; CHECK-LABEL: commute_subop0_zext: 764; CHECK: // %bb.0: 765; CHECK-NEXT: sub w8, w2, w1 766; CHECK-NEXT: add w0, w8, w0, uxth 767; CHECK-NEXT: ret 768 %zext = zext i16 %x to i32 769 %sub = sub i32 %zext, %y 770 %add = add i32 %sub, %z 771 ret i32 %add 772} 773 774 775; ((anyext X) - Y) + Z --> (Z - Y) + (anyext X) 776define i8 @commute_subop0_anyext(i16 %a, i16 %b, i32 %c) { 777; CHECK-LABEL: commute_subop0_anyext: 778; CHECK: // %bb.0: 779; CHECK-NEXT: mov w8, #111 // =0x6f 780; CHECK-NEXT: sub w9, w2, w1 781; CHECK-NEXT: madd w8, w0, w8, w9 782; CHECK-NEXT: lsl w8, w8, #3 783; CHECK-NEXT: sub w0, w8, #1776 784; CHECK-NEXT: ret 785 %aa = mul i16 %a, 111 786 %bb = add i16 %b, 222 787 %a_32 = zext i16 %aa to i32 788 %b_32 = zext i16 %bb to i32 789 %sub = sub i32 %a_32, %b_32 790 %add = add i32 %sub, %c 791 %trunc = trunc i32 %add to i8 792 %r = shl i8 %trunc, 3 793 ret i8 %r 794} 795 796; ((X and C) - Y) + Z --> (Z - Y) + (X and C) 797define i32 @commute_subop0_and(i32 %x, i32 %y, i32 %z) { 798; CHECK-LABEL: commute_subop0_and: 799; CHECK: // %bb.0: 800; CHECK-NEXT: sub w8, w2, w1 801; CHECK-NEXT: add w0, w8, w0, uxtb 802; CHECK-NEXT: ret 803 %and = and i32 %x, 255 804 %sub = sub i32 %and, %y 805 %add = add i32 %sub, %z 806 ret i32 %add 807} 808 809; Z + ((X << C) - Y) --> (Z - Y) + (X << C) 810define i32 @commute_subop0_cadd(i32 %x, i32 %y, i32 %z) { 811; CHECK-LABEL: commute_subop0_cadd: 812; CHECK: // %bb.0: 813; CHECK-NEXT: sub w8, w2, w1 814; CHECK-NEXT: add w0, w8, w0, lsl #3 815; CHECK-NEXT: ret 816 %shl = shl i32 %x, 3 817 %sub = sub i32 %shl, %y 818 %add = add i32 %z, %sub 819 ret i32 %add 820} 821 822; Y + ((X << C) - X) --> (Y - X) + (X << C) 823define i32 @commute_subop0_mul(i32 %x, i32 %y) { 824; CHECK-LABEL: commute_subop0_mul: 825; CHECK: // %bb.0: 826; CHECK-NEXT: sub w8, w1, w0 827; CHECK-NEXT: add w0, w8, w0, lsl #3 828; CHECK-NEXT: ret 829 %mul = mul i32 %x, 7 830 %add = add i32 %mul, %y 831 ret i32 %add 832} 833 834; negative case for ((X << C) - Y) + Z --> (Z - Y) + (X << C) 835; Y can't be constant to avoid dead loop 836define i32 @commute_subop0_zconst(i32 %x, i32 %y) { 837; CHECK-LABEL: commute_subop0_zconst: 838; CHECK: // %bb.0: 839; CHECK-NEXT: lsl w8, w0, #3 840; CHECK-NEXT: sub w8, w8, w1 841; CHECK-NEXT: add w0, w8, #1 842; CHECK-NEXT: ret 843 %shl = shl i32 %x, 3 844 %sub = sub i32 %shl, %y 845 %add = add i32 %sub, 1 846 ret i32 %add 847} 848 849; negative case for ((X << C) - Y) + Z --> (Z - Y) + (X << C) 850; Y can't be shift C also to avoid dead loop 851define i32 @commute_subop0_zshiftc_oneuse(i32 %x, i32 %y, i32 %z) { 852; CHECK-LABEL: commute_subop0_zshiftc_oneuse: 853; CHECK: // %bb.0: 854; CHECK-NEXT: lsl w8, w0, #3 855; CHECK-NEXT: sub w8, w8, w1 856; CHECK-NEXT: add w0, w8, w2, lsl #2 857; CHECK-NEXT: ret 858 %xshl = shl i32 %x, 3 859 %sub = sub i32 %xshl, %y 860 %zshl = shl i32 %z, 2 861 %add = add i32 %sub, %zshl 862 ret i32 %add 863} 864 865define i32 @commute_subop0_zshiftc(i32 %x, i32 %y, i32 %z) { 866; CHECK-LABEL: commute_subop0_zshiftc: 867; CHECK: // %bb.0: 868; CHECK-NEXT: lsl w8, w2, #2 869; CHECK-NEXT: sub w9, w8, w1 870; CHECK-NEXT: add w9, w9, w0, lsl #3 871; CHECK-NEXT: eor w0, w8, w9 872; CHECK-NEXT: ret 873 %xshl = shl i32 %x, 3 874 %sub = sub i32 %xshl, %y 875 %zshl = shl i32 %z, 2 876 %add = add i32 %sub, %zshl 877 %r = xor i32 %zshl, %add 878 ret i32 %r 879} 880