614 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -debugify-and-strip-all-safe -enable-machine-outliner=never -verify-machineinstrs %s -o - -mtriple=aarch64-linux-gnu -aarch64-enable-atomic-cfg-tidy=0 | FileCheck %s3; RUN: llc -debugify-and-strip-all-safe -global-isel -enable-machine-outliner=never -verify-machineinstrs %s -o - -mtriple=aarch64-linux-gnu -aarch64-enable-atomic-cfg-tidy=0 | FileCheck %s4 5define i32 @add_z_i8i32(i8 %v, i32 %lhs) minsize {6; CHECK-LABEL: add_z_i8i32:7; CHECK: // %bb.0:8; CHECK-NEXT: add w0, w1, w0, uxtb9; CHECK-NEXT: ret10 %vz = zext i8 %v to i3211 %r = add i32 %lhs, %vz12 ret i32 %r13}14 15define i32 @add_z_shli8i32(i8 %v, i32 %lhs) minsize {16; CHECK-LABEL: add_z_shli8i32:17; CHECK: // %bb.0:18; CHECK-NEXT: add w0, w1, w0, uxtb #319; CHECK-NEXT: ret20 %vz = zext i8 %v to i3221 %s = shl i32 %vz, 322 %r = add i32 %lhs, %s23 ret i32 %r24}25 26define i64 @add_z_i8i64(i8 %v, i64 %lhs) minsize {27; CHECK-LABEL: add_z_i8i64:28; CHECK: // %bb.0:29; CHECK-NEXT: add x0, x1, w0, uxtb30; CHECK-NEXT: ret31 %vz = zext i8 %v to i6432 %r = add i64 %lhs, %vz33 ret i64 %r34}35 36define i64 @add_z_shli8i64(i8 %v, i64 %lhs) minsize {37; CHECK-LABEL: add_z_shli8i64:38; CHECK: // %bb.0:39; CHECK-NEXT: add x0, x1, w0, uxtb #340; CHECK-NEXT: ret41 %vz = zext i8 %v to i6442 %s = shl i64 %vz, 343 %r = add i64 %lhs, %s44 ret i64 %r45}46 47define i32 @add_s_i8i32(i8 %v, i32 %lhs) minsize {48; CHECK-LABEL: add_s_i8i32:49; CHECK: // %bb.0:50; CHECK-NEXT: add w0, w1, w0, sxtb51; CHECK-NEXT: ret52 %vz = sext i8 %v to i3253 %r = add i32 %lhs, %vz54 ret i32 %r55}56 57define i32 @add_s_shli8i32(i8 %v, i32 %lhs) minsize {58; CHECK-LABEL: add_s_shli8i32:59; CHECK: // %bb.0:60; CHECK-NEXT: add w0, w1, w0, sxtb #361; CHECK-NEXT: ret62 %vz = sext i8 %v to i3263 %s = shl i32 %vz, 364 %r = add i32 %lhs, %s65 ret i32 %r66}67 68define i64 @add_s_i8i64(i8 %v, i64 %lhs) minsize {69; CHECK-LABEL: add_s_i8i64:70; CHECK: // %bb.0:71; CHECK-NEXT: add x0, x1, w0, sxtb72; CHECK-NEXT: ret73 %vz = sext i8 %v to i6474 %r = add i64 %lhs, %vz75 ret i64 %r76}77 78define i64 @add_s_shli8i64(i8 %v, i64 %lhs) minsize {79; CHECK-LABEL: add_s_shli8i64:80; CHECK: // %bb.0:81; CHECK-NEXT: add x0, x1, w0, sxtb #382; CHECK-NEXT: ret83 %vz = sext i8 %v to i6484 %s = shl i64 %vz, 385 %r = add i64 %lhs, %s86 ret i64 %r87}88 89define i32 @add_z_i16i32(i16 %v, i32 %lhs) minsize {90; CHECK-LABEL: add_z_i16i32:91; CHECK: // %bb.0:92; CHECK-NEXT: add w0, w1, w0, uxth93; CHECK-NEXT: ret94 %vz = zext i16 %v to i3295 %r = add i32 %lhs, %vz96 ret i32 %r97}98 99define i32 @add_z_shli16i32(i16 %v, i32 %lhs) minsize {100; CHECK-LABEL: add_z_shli16i32:101; CHECK: // %bb.0:102; CHECK-NEXT: add w0, w1, w0, uxth #3103; CHECK-NEXT: ret104 %vz = zext i16 %v to i32105 %s = shl i32 %vz, 3106 %r = add i32 %lhs, %s107 ret i32 %r108}109 110define i64 @add_z_i16i64(i16 %v, i64 %lhs) minsize {111; CHECK-LABEL: add_z_i16i64:112; CHECK: // %bb.0:113; CHECK-NEXT: add x0, x1, w0, uxth114; CHECK-NEXT: ret115 %vz = zext i16 %v to i64116 %r = add i64 %lhs, %vz117 ret i64 %r118}119 120define i64 @add_z_shli16i64(i16 %v, i64 %lhs) minsize {121; CHECK-LABEL: add_z_shli16i64:122; CHECK: // %bb.0:123; CHECK-NEXT: add x0, x1, w0, uxth #3124; CHECK-NEXT: ret125 %vz = zext i16 %v to i64126 %s = shl i64 %vz, 3127 %r = add i64 %lhs, %s128 ret i64 %r129}130 131define i64 @add_z_i32i64(i32 %v, i64 %lhs) minsize {132; CHECK-LABEL: add_z_i32i64:133; CHECK: // %bb.0:134; CHECK-NEXT: add x0, x1, w0, uxtw135; CHECK-NEXT: ret136 %vz = zext i32 %v to i64137 %r = add i64 %lhs, %vz138 ret i64 %r139}140 141define i64 @add_z_shli32i64(i32 %v, i64 %lhs) minsize {142; CHECK-LABEL: add_z_shli32i64:143; CHECK: // %bb.0:144; CHECK-NEXT: add x0, x1, w0, uxtw #3145; CHECK-NEXT: ret146 %vz = zext i32 %v to i64147 %s = shl i64 %vz, 3148 %r = add i64 %lhs, %s149 ret i64 %r150}151 152define i32 @add_s_i16i32(i16 %v, i32 %lhs) minsize {153; CHECK-LABEL: add_s_i16i32:154; CHECK: // %bb.0:155; CHECK-NEXT: add w0, w1, w0, sxth156; CHECK-NEXT: ret157 %vz = sext i16 %v to i32158 %r = add i32 %lhs, %vz159 ret i32 %r160}161 162define i32 @add_s_shli16i32(i16 %v, i32 %lhs) minsize {163; CHECK-LABEL: add_s_shli16i32:164; CHECK: // %bb.0:165; CHECK-NEXT: add w0, w1, w0, sxth #3166; CHECK-NEXT: ret167 %vz = sext i16 %v to i32168 %s = shl i32 %vz, 3169 %r = add i32 %lhs, %s170 ret i32 %r171}172 173define i64 @add_s_i16i64(i16 %v, i64 %lhs) minsize {174; CHECK-LABEL: add_s_i16i64:175; CHECK: // %bb.0:176; CHECK-NEXT: add x0, x1, w0, sxth177; CHECK-NEXT: ret178 %vz = sext i16 %v to i64179 %r = add i64 %lhs, %vz180 ret i64 %r181}182 183define i64 @add_s_shli16i64(i16 %v, i64 %lhs) minsize {184; CHECK-LABEL: add_s_shli16i64:185; CHECK: // %bb.0:186; CHECK-NEXT: add x0, x1, w0, sxth #3187; CHECK-NEXT: ret188 %vz = sext i16 %v to i64189 %s = shl i64 %vz, 3190 %r = add i64 %lhs, %s191 ret i64 %r192}193 194define i64 @add_s_i32i64(i32 %v, i64 %lhs) minsize {195; CHECK-LABEL: add_s_i32i64:196; CHECK: // %bb.0:197; CHECK-NEXT: add x0, x1, w0, sxtw198; CHECK-NEXT: ret199 %vz = sext i32 %v to i64200 %r = add i64 %lhs, %vz201 ret i64 %r202}203 204define i64 @add_s_shli32i64(i32 %v, i64 %lhs) minsize {205; CHECK-LABEL: add_s_shli32i64:206; CHECK: // %bb.0:207; CHECK-NEXT: add x0, x1, w0, sxtw #3208; CHECK-NEXT: ret209 %vz = sext i32 %v to i64210 %s = shl i64 %vz, 3211 %r = add i64 %lhs, %s212 ret i64 %r213}214 215define i32 @sub_z_i8i32(i8 %v, i32 %lhs) minsize {216; CHECK-LABEL: sub_z_i8i32:217; CHECK: // %bb.0:218; CHECK-NEXT: sub w0, w1, w0, uxtb219; CHECK-NEXT: ret220 %vz = zext i8 %v to i32221 %r = sub i32 %lhs, %vz222 ret i32 %r223}224 225define i32 @sub_z_shli8i32(i8 %v, i32 %lhs) minsize {226; CHECK-LABEL: sub_z_shli8i32:227; CHECK: // %bb.0:228; CHECK-NEXT: sub w0, w1, w0, uxtb #3229; CHECK-NEXT: ret230 %vz = zext i8 %v to i32231 %s = shl i32 %vz, 3232 %r = sub i32 %lhs, %s233 ret i32 %r234}235 236define i64 @sub_z_i8i64(i8 %v, i64 %lhs) minsize {237; CHECK-LABEL: sub_z_i8i64:238; CHECK: // %bb.0:239; CHECK-NEXT: sub x0, x1, w0, uxtb240; CHECK-NEXT: ret241 %vz = zext i8 %v to i64242 %r = sub i64 %lhs, %vz243 ret i64 %r244}245 246define i64 @sub_z_shli8i64(i8 %v, i64 %lhs) minsize {247; CHECK-LABEL: sub_z_shli8i64:248; CHECK: // %bb.0:249; CHECK-NEXT: sub x0, x1, w0, uxtb #3250; CHECK-NEXT: ret251 %vz = zext i8 %v to i64252 %s = shl i64 %vz, 3253 %r = sub i64 %lhs, %s254 ret i64 %r255}256 257define i32 @sub_s_i8i32(i8 %v, i32 %lhs) minsize {258; CHECK-LABEL: sub_s_i8i32:259; CHECK: // %bb.0:260; CHECK-NEXT: sub w0, w1, w0, sxtb261; CHECK-NEXT: ret262 %vz = sext i8 %v to i32263 %r = sub i32 %lhs, %vz264 ret i32 %r265}266 267define i32 @sub_s_shli8i32(i8 %v, i32 %lhs) minsize {268; CHECK-LABEL: sub_s_shli8i32:269; CHECK: // %bb.0:270; CHECK-NEXT: sub w0, w1, w0, sxtb #3271; CHECK-NEXT: ret272 %vz = sext i8 %v to i32273 %s = shl i32 %vz, 3274 %r = sub i32 %lhs, %s275 ret i32 %r276}277 278define i64 @sub_s_i8i64(i8 %v, i64 %lhs) minsize {279; CHECK-LABEL: sub_s_i8i64:280; CHECK: // %bb.0:281; CHECK-NEXT: sub x0, x1, w0, sxtb282; CHECK-NEXT: ret283 %vz = sext i8 %v to i64284 %r = sub i64 %lhs, %vz285 ret i64 %r286}287 288define i64 @sub_s_shli8i64(i8 %v, i64 %lhs) minsize {289; CHECK-LABEL: sub_s_shli8i64:290; CHECK: // %bb.0:291; CHECK-NEXT: sub x0, x1, w0, sxtb #3292; CHECK-NEXT: ret293 %vz = sext i8 %v to i64294 %s = shl i64 %vz, 3295 %r = sub i64 %lhs, %s296 ret i64 %r297}298 299define i32 @sub_z_i16i32(i16 %v, i32 %lhs) minsize {300; CHECK-LABEL: sub_z_i16i32:301; CHECK: // %bb.0:302; CHECK-NEXT: sub w0, w1, w0, uxth303; CHECK-NEXT: ret304 %vz = zext i16 %v to i32305 %r = sub i32 %lhs, %vz306 ret i32 %r307}308 309define i32 @sub_z_shli16i32(i16 %v, i32 %lhs) minsize {310; CHECK-LABEL: sub_z_shli16i32:311; CHECK: // %bb.0:312; CHECK-NEXT: sub w0, w1, w0, uxth #3313; CHECK-NEXT: ret314 %vz = zext i16 %v to i32315 %s = shl i32 %vz, 3316 %r = sub i32 %lhs, %s317 ret i32 %r318}319 320define i64 @sub_z_i16i64(i16 %v, i64 %lhs) minsize {321; CHECK-LABEL: sub_z_i16i64:322; CHECK: // %bb.0:323; CHECK-NEXT: sub x0, x1, w0, uxth324; CHECK-NEXT: ret325 %vz = zext i16 %v to i64326 %r = sub i64 %lhs, %vz327 ret i64 %r328}329 330define i64 @sub_z_shli16i64(i16 %v, i64 %lhs) minsize {331; CHECK-LABEL: sub_z_shli16i64:332; CHECK: // %bb.0:333; CHECK-NEXT: sub x0, x1, w0, uxth #3334; CHECK-NEXT: ret335 %vz = zext i16 %v to i64336 %s = shl i64 %vz, 3337 %r = sub i64 %lhs, %s338 ret i64 %r339}340 341define i64 @sub_z_i32i64(i32 %v, i64 %lhs) minsize {342; CHECK-LABEL: sub_z_i32i64:343; CHECK: // %bb.0:344; CHECK-NEXT: sub x0, x1, w0, uxtw345; CHECK-NEXT: ret346 %vz = zext i32 %v to i64347 %r = sub i64 %lhs, %vz348 ret i64 %r349}350 351define i64 @sub_z_shli32i64(i32 %v, i64 %lhs) minsize {352; CHECK-LABEL: sub_z_shli32i64:353; CHECK: // %bb.0:354; CHECK-NEXT: sub x0, x1, w0, uxtw #3355; CHECK-NEXT: ret356 %vz = zext i32 %v to i64357 %s = shl i64 %vz, 3358 %r = sub i64 %lhs, %s359 ret i64 %r360}361 362define i32 @sub_s_i16i32(i16 %v, i32 %lhs) minsize {363; CHECK-LABEL: sub_s_i16i32:364; CHECK: // %bb.0:365; CHECK-NEXT: sub w0, w1, w0, sxth366; CHECK-NEXT: ret367 %vz = sext i16 %v to i32368 %r = sub i32 %lhs, %vz369 ret i32 %r370}371 372define i32 @sub_s_shli16i32(i16 %v, i32 %lhs) minsize {373; CHECK-LABEL: sub_s_shli16i32:374; CHECK: // %bb.0:375; CHECK-NEXT: sub w0, w1, w0, sxth #3376; CHECK-NEXT: ret377 %vz = sext i16 %v to i32378 %s = shl i32 %vz, 3379 %r = sub i32 %lhs, %s380 ret i32 %r381}382 383define i64 @sub_s_i16i64(i16 %v, i64 %lhs) minsize {384; CHECK-LABEL: sub_s_i16i64:385; CHECK: // %bb.0:386; CHECK-NEXT: sub x0, x1, w0, sxth387; CHECK-NEXT: ret388 %vz = sext i16 %v to i64389 %r = sub i64 %lhs, %vz390 ret i64 %r391}392 393define i64 @sub_s_shli16i64(i16 %v, i64 %lhs) minsize {394; CHECK-LABEL: sub_s_shli16i64:395; CHECK: // %bb.0:396; CHECK-NEXT: sub x0, x1, w0, sxth #3397; CHECK-NEXT: ret398 %vz = sext i16 %v to i64399 %s = shl i64 %vz, 3400 %r = sub i64 %lhs, %s401 ret i64 %r402}403 404define i64 @sub_s_i32i64(i32 %v, i64 %lhs) minsize {405; CHECK-LABEL: sub_s_i32i64:406; CHECK: // %bb.0:407; CHECK-NEXT: sub x0, x1, w0, sxtw408; CHECK-NEXT: ret409 %vz = sext i32 %v to i64410 %r = sub i64 %lhs, %vz411 ret i64 %r412}413 414define i64 @sub_s_shli32i64(i32 %v, i64 %lhs) minsize {415; CHECK-LABEL: sub_s_shli32i64:416; CHECK: // %bb.0:417; CHECK-NEXT: sub x0, x1, w0, sxtw #3418; CHECK-NEXT: ret419 %vz = sext i32 %v to i64420 %s = shl i64 %vz, 3421 %r = sub i64 %lhs, %s422 ret i64 %r423}424 425define i32 @cmp_s_i8i32(i8 %v, i32 %lhs) minsize {426; CHECK-LABEL: cmp_s_i8i32:427; CHECK: // %bb.0:428; CHECK-NEXT: cmp w1, w0, uxtb429; CHECK-NEXT: b.ge .LBB40_2430; CHECK-NEXT: // %bb.1: // %then431; CHECK-NEXT: mov w0, #1 // =0x1432; CHECK-NEXT: ret433; CHECK-NEXT: .LBB40_2: // %end434; CHECK-NEXT: mov w0, w1435; CHECK-NEXT: ret436 %vz = zext i8 %v to i32437 %c = icmp slt i32 %lhs, %vz438 br i1 %c, label %then, label %end439then:440 ret i32 1441end:442 ret i32 %lhs443}444 445define i64 @cmp_s_i8i64(i8 %v, i64 %lhs) minsize {446; CHECK-LABEL: cmp_s_i8i64:447; CHECK: // %bb.0:448; CHECK-NEXT: cmp x1, w0, sxtb449; CHECK-NEXT: b.ge .LBB41_2450; CHECK-NEXT: // %bb.1: // %then451; CHECK-NEXT: mov w0, #1 // =0x1452; CHECK-NEXT: ret453; CHECK-NEXT: .LBB41_2: // %end454; CHECK-NEXT: mov x0, x1455; CHECK-NEXT: ret456 %vz = sext i8 %v to i64457 %c = icmp slt i64 %lhs, %vz458 br i1 %c, label %then, label %end459then:460 ret i64 1461end:462 ret i64 %lhs463}464 465define i32 @cmp_s_i16i32(i16 %v, i32 %lhs) minsize {466; CHECK-LABEL: cmp_s_i16i32:467; CHECK: // %bb.0:468; CHECK-NEXT: cmp w1, w0, uxth469; CHECK-NEXT: b.ge .LBB42_2470; CHECK-NEXT: // %bb.1: // %then471; CHECK-NEXT: mov w0, #1 // =0x1472; CHECK-NEXT: ret473; CHECK-NEXT: .LBB42_2: // %end474; CHECK-NEXT: mov w0, w1475; CHECK-NEXT: ret476 %vz = zext i16 %v to i32477 %c = icmp slt i32 %lhs, %vz478 br i1 %c, label %then, label %end479then:480 ret i32 1481end:482 ret i32 %lhs483}484 485define i64 @cmp_s_i16i64(i16 %v, i64 %lhs) minsize {486; CHECK-LABEL: cmp_s_i16i64:487; CHECK: // %bb.0:488; CHECK-NEXT: cmp x1, w0, sxth489; CHECK-NEXT: b.ge .LBB43_2490; CHECK-NEXT: // %bb.1: // %then491; CHECK-NEXT: mov w0, #1 // =0x1492; CHECK-NEXT: ret493; CHECK-NEXT: .LBB43_2: // %end494; CHECK-NEXT: mov x0, x1495; CHECK-NEXT: ret496 %vz = sext i16 %v to i64497 %c = icmp slt i64 %lhs, %vz498 br i1 %c, label %then, label %end499then:500 ret i64 1501end:502 ret i64 %lhs503}504 505 506; Check that implicit zext from w reg write is used instead of uxtw form of add.507define dso_local i64 @add_fold_uxtw(i32 %x, i64 %y) {508; CHECK-LABEL: add_fold_uxtw:509; CHECK: // %bb.0: // %entry510; CHECK-NEXT: and w8, w0, #0x3511; CHECK-NEXT: add x0, x1, x8512; CHECK-NEXT: ret513entry:514 %m = and i32 %x, 3515 %ext = zext i32 %m to i64516 %ret = add i64 %y, %ext517 ret i64 %ret518}519 520; Check that implicit zext from w reg write is used instead of uxtw521; form of sub and that mov WZR is folded to form a neg instruction.522define dso_local i64 @sub_fold_uxtw_xzr(i32 %x) {523; CHECK-LABEL: sub_fold_uxtw_xzr:524; CHECK: // %bb.0: // %entry525; CHECK-NEXT: and w8, w0, #0x3526; CHECK-NEXT: neg x0, x8527; CHECK-NEXT: ret528entry:529 %m = and i32 %x, 3530 %ext = zext i32 %m to i64531 %ret = sub i64 0, %ext532 ret i64 %ret533}534 535; Check that implicit zext from w reg write is used instead of uxtw form of subs/cmp.536define dso_local i1 @cmp_fold_uxtw(i32 %x, i64 %y) {537; CHECK-LABEL: cmp_fold_uxtw:538; CHECK: // %bb.0: // %entry539; CHECK-NEXT: and w8, w0, #0x3540; CHECK-NEXT: cmp x1, x8541; CHECK-NEXT: cset w0, eq542; CHECK-NEXT: ret543entry:544 %m = and i32 %x, 3545 %ext = zext i32 %m to i64546 %ret = icmp eq i64 %y, %ext547 ret i1 %ret548}549 550; Check that implicit zext from w reg write is used instead of uxtw551; form of add, leading to madd selection.552define dso_local i64 @madd_fold_uxtw(i32 %x, i64 %y) {553; CHECK-LABEL: madd_fold_uxtw:554; CHECK: // %bb.0: // %entry555; CHECK-NEXT: and w8, w0, #0x3556; CHECK-NEXT: madd x0, x1, x1, x8557; CHECK-NEXT: ret558entry:559 %m = and i32 %x, 3560 %ext = zext i32 %m to i64561 %mul = mul i64 %y, %y562 %ret = add i64 %mul, %ext563 ret i64 %ret564}565 566; Check that implicit zext from w reg write is used instead of uxtw567; form of sub, leading to sub/cmp folding.568; Check that implicit zext from w reg write is used instead of uxtw form of subs/cmp.569define dso_local i1 @cmp_sub_fold_uxtw(i32 %x, i64 %y, i64 %z) {570; CHECK-LABEL: cmp_sub_fold_uxtw:571; CHECK: // %bb.0: // %entry572; CHECK-NEXT: and w8, w0, #0x3573; CHECK-NEXT: cmp x2, x8574; CHECK-NEXT: cset w0, eq575; CHECK-NEXT: ret576entry:577 %m = and i32 %x, 3578 %ext = zext i32 %m to i64579 %sub = sub i64 %z, %ext580 %ret = icmp eq i64 %sub, 0581 ret i1 %ret582}583 584; Check that implicit zext from w reg write is used instead of uxtw585; form of add and add of -1 gets selected as sub.586define dso_local i64 @add_imm_fold_uxtw(i32 %x) {587; CHECK-LABEL: add_imm_fold_uxtw:588; CHECK: // %bb.0: // %entry589; CHECK-NEXT: and w8, w0, #0x3590; CHECK-NEXT: sub x0, x8, #1591; CHECK-NEXT: ret592entry:593 %m = and i32 %x, 3594 %ext = zext i32 %m to i64595 %ret = add i64 %ext, -1596 ret i64 %ret597}598 599; Check that implicit zext from w reg write is used instead of uxtw600; form of add and add lsl form gets selected.601define dso_local i64 @add_lsl_fold_uxtw(i32 %x, i64 %y) {602; CHECK-LABEL: add_lsl_fold_uxtw:603; CHECK: // %bb.0: // %entry604; CHECK-NEXT: orr w8, w0, #0x3605; CHECK-NEXT: add x0, x8, x1, lsl #3606; CHECK-NEXT: ret607entry:608 %m = or i32 %x, 3609 %ext = zext i32 %m to i64610 %shift = shl i64 %y, 3611 %ret = add i64 %ext, %shift612 ret i64 %ret613}614