320 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc < %s -mtriple=aarch64-unknown-unknown | FileCheck %s --check-prefix=ALL3 4; If the target does not have a single div/rem operation,5; -div-rem-pairs pass will decompose the remainder calculation as:6; X % Y --> X - ((X / Y) * Y)7; But if the target does have a single div/rem operation,8; the opposite transform is likely beneficial.9 10define i8 @scalar_i8(i8 %x, i8 %y, ptr %divdst) nounwind {11; ALL-LABEL: scalar_i8:12; ALL: // %bb.0:13; ALL-NEXT: sxtb w8, w114; ALL-NEXT: sxtb w9, w015; ALL-NEXT: sdiv w8, w9, w816; ALL-NEXT: msub w0, w8, w1, w017; ALL-NEXT: strb w8, [x2]18; ALL-NEXT: ret19 %div = sdiv i8 %x, %y20 store i8 %div, ptr %divdst, align 421 %t1 = mul i8 %div, %y22 %t2 = sub i8 %x, %t123 ret i8 %t224}25 26define i16 @scalar_i16(i16 %x, i16 %y, ptr %divdst) nounwind {27; ALL-LABEL: scalar_i16:28; ALL: // %bb.0:29; ALL-NEXT: sxth w8, w130; ALL-NEXT: sxth w9, w031; ALL-NEXT: sdiv w8, w9, w832; ALL-NEXT: msub w0, w8, w1, w033; ALL-NEXT: strh w8, [x2]34; ALL-NEXT: ret35 %div = sdiv i16 %x, %y36 store i16 %div, ptr %divdst, align 437 %t1 = mul i16 %div, %y38 %t2 = sub i16 %x, %t139 ret i16 %t240}41 42define i32 @scalar_i32(i32 %x, i32 %y, ptr %divdst) nounwind {43; ALL-LABEL: scalar_i32:44; ALL: // %bb.0:45; ALL-NEXT: sdiv w8, w0, w146; ALL-NEXT: msub w0, w8, w1, w047; ALL-NEXT: str w8, [x2]48; ALL-NEXT: ret49 %div = sdiv i32 %x, %y50 store i32 %div, ptr %divdst, align 451 %t1 = mul i32 %div, %y52 %t2 = sub i32 %x, %t153 ret i32 %t254}55 56define i64 @scalar_i64(i64 %x, i64 %y, ptr %divdst) nounwind {57; ALL-LABEL: scalar_i64:58; ALL: // %bb.0:59; ALL-NEXT: sdiv x8, x0, x160; ALL-NEXT: msub x0, x8, x1, x061; ALL-NEXT: str x8, [x2]62; ALL-NEXT: ret63 %div = sdiv i64 %x, %y64 store i64 %div, ptr %divdst, align 465 %t1 = mul i64 %div, %y66 %t2 = sub i64 %x, %t167 ret i64 %t268}69 70define <16 x i8> @vector_i128_i8(<16 x i8> %x, <16 x i8> %y, ptr %divdst) nounwind {71; ALL-LABEL: vector_i128_i8:72; ALL: // %bb.0:73; ALL-NEXT: smov w8, v1.b[1]74; ALL-NEXT: smov w9, v0.b[1]75; ALL-NEXT: smov w10, v0.b[0]76; ALL-NEXT: smov w11, v0.b[2]77; ALL-NEXT: smov w12, v0.b[3]78; ALL-NEXT: smov w13, v0.b[4]79; ALL-NEXT: smov w14, v0.b[5]80; ALL-NEXT: smov w15, v0.b[6]81; ALL-NEXT: smov w16, v0.b[7]82; ALL-NEXT: smov w17, v0.b[8]83; ALL-NEXT: smov w18, v0.b[9]84; ALL-NEXT: sdiv w8, w9, w885; ALL-NEXT: smov w9, v1.b[0]86; ALL-NEXT: sdiv w9, w10, w987; ALL-NEXT: smov w10, v1.b[2]88; ALL-NEXT: sdiv w10, w11, w1089; ALL-NEXT: smov w11, v1.b[3]90; ALL-NEXT: fmov s2, w991; ALL-NEXT: smov w9, v1.b[10]92; ALL-NEXT: mov v2.b[1], w893; ALL-NEXT: sdiv w11, w12, w1194; ALL-NEXT: smov w12, v1.b[4]95; ALL-NEXT: mov v2.b[2], w1096; ALL-NEXT: smov w10, v0.b[10]97; ALL-NEXT: sdiv w12, w13, w1298; ALL-NEXT: smov w13, v1.b[5]99; ALL-NEXT: mov v2.b[3], w11100; ALL-NEXT: smov w11, v0.b[11]101; ALL-NEXT: sdiv w13, w14, w13102; ALL-NEXT: smov w14, v1.b[6]103; ALL-NEXT: mov v2.b[4], w12104; ALL-NEXT: smov w12, v0.b[12]105; ALL-NEXT: sdiv w14, w15, w14106; ALL-NEXT: smov w15, v1.b[7]107; ALL-NEXT: mov v2.b[5], w13108; ALL-NEXT: smov w13, v0.b[13]109; ALL-NEXT: sdiv w15, w16, w15110; ALL-NEXT: smov w16, v1.b[8]111; ALL-NEXT: mov v2.b[6], w14112; ALL-NEXT: sdiv w16, w17, w16113; ALL-NEXT: smov w17, v1.b[9]114; ALL-NEXT: mov v2.b[7], w15115; ALL-NEXT: sdiv w8, w18, w17116; ALL-NEXT: mov v2.b[8], w16117; ALL-NEXT: sdiv w9, w10, w9118; ALL-NEXT: smov w10, v1.b[11]119; ALL-NEXT: mov v2.b[9], w8120; ALL-NEXT: sdiv w10, w11, w10121; ALL-NEXT: smov w11, v1.b[12]122; ALL-NEXT: mov v2.b[10], w9123; ALL-NEXT: smov w9, v1.b[14]124; ALL-NEXT: sdiv w11, w12, w11125; ALL-NEXT: smov w12, v1.b[13]126; ALL-NEXT: mov v2.b[11], w10127; ALL-NEXT: smov w10, v1.b[15]128; ALL-NEXT: sdiv w8, w13, w12129; ALL-NEXT: smov w12, v0.b[14]130; ALL-NEXT: mov v2.b[12], w11131; ALL-NEXT: smov w11, v0.b[15]132; ALL-NEXT: sdiv w9, w12, w9133; ALL-NEXT: mov v2.b[13], w8134; ALL-NEXT: sdiv w8, w11, w10135; ALL-NEXT: mov v2.b[14], w9136; ALL-NEXT: mov v2.b[15], w8137; ALL-NEXT: mls v0.16b, v2.16b, v1.16b138; ALL-NEXT: str q2, [x0]139; ALL-NEXT: ret140 %div = sdiv <16 x i8> %x, %y141 store <16 x i8> %div, ptr %divdst, align 16142 %t1 = mul <16 x i8> %div, %y143 %t2 = sub <16 x i8> %x, %t1144 ret <16 x i8> %t2145}146 147define <8 x i16> @vector_i128_i16(<8 x i16> %x, <8 x i16> %y, ptr %divdst) nounwind {148; ALL-LABEL: vector_i128_i16:149; ALL: // %bb.0:150; ALL-NEXT: smov w8, v1.h[1]151; ALL-NEXT: smov w9, v0.h[1]152; ALL-NEXT: smov w10, v0.h[0]153; ALL-NEXT: smov w11, v0.h[2]154; ALL-NEXT: smov w12, v0.h[3]155; ALL-NEXT: smov w13, v0.h[4]156; ALL-NEXT: smov w14, v0.h[5]157; ALL-NEXT: sdiv w8, w9, w8158; ALL-NEXT: smov w9, v1.h[0]159; ALL-NEXT: sdiv w9, w10, w9160; ALL-NEXT: smov w10, v1.h[2]161; ALL-NEXT: sdiv w10, w11, w10162; ALL-NEXT: smov w11, v1.h[3]163; ALL-NEXT: fmov s2, w9164; ALL-NEXT: smov w9, v1.h[6]165; ALL-NEXT: mov v2.h[1], w8166; ALL-NEXT: sdiv w11, w12, w11167; ALL-NEXT: smov w12, v1.h[4]168; ALL-NEXT: mov v2.h[2], w10169; ALL-NEXT: smov w10, v0.h[6]170; ALL-NEXT: sdiv w12, w13, w12171; ALL-NEXT: smov w13, v1.h[5]172; ALL-NEXT: mov v2.h[3], w11173; ALL-NEXT: smov w11, v0.h[7]174; ALL-NEXT: sdiv w8, w14, w13175; ALL-NEXT: mov v2.h[4], w12176; ALL-NEXT: sdiv w9, w10, w9177; ALL-NEXT: smov w10, v1.h[7]178; ALL-NEXT: mov v2.h[5], w8179; ALL-NEXT: sdiv w8, w11, w10180; ALL-NEXT: mov v2.h[6], w9181; ALL-NEXT: mov v2.h[7], w8182; ALL-NEXT: mls v0.8h, v2.8h, v1.8h183; ALL-NEXT: str q2, [x0]184; ALL-NEXT: ret185 %div = sdiv <8 x i16> %x, %y186 store <8 x i16> %div, ptr %divdst, align 16187 %t1 = mul <8 x i16> %div, %y188 %t2 = sub <8 x i16> %x, %t1189 ret <8 x i16> %t2190}191 192define <4 x i32> @vector_i128_i32(<4 x i32> %x, <4 x i32> %y, ptr %divdst) nounwind {193; ALL-LABEL: vector_i128_i32:194; ALL: // %bb.0:195; ALL-NEXT: mov w8, v1.s[1]196; ALL-NEXT: mov w9, v0.s[1]197; ALL-NEXT: fmov w10, s0198; ALL-NEXT: mov w11, v0.s[2]199; ALL-NEXT: mov w12, v0.s[3]200; ALL-NEXT: sdiv w8, w9, w8201; ALL-NEXT: fmov w9, s1202; ALL-NEXT: sdiv w9, w10, w9203; ALL-NEXT: mov w10, v1.s[2]204; ALL-NEXT: sdiv w10, w11, w10205; ALL-NEXT: mov w11, v1.s[3]206; ALL-NEXT: fmov s2, w9207; ALL-NEXT: mov v2.s[1], w8208; ALL-NEXT: sdiv w8, w12, w11209; ALL-NEXT: mov v2.s[2], w10210; ALL-NEXT: mov v2.s[3], w8211; ALL-NEXT: mls v0.4s, v2.4s, v1.4s212; ALL-NEXT: str q2, [x0]213; ALL-NEXT: ret214 %div = sdiv <4 x i32> %x, %y215 store <4 x i32> %div, ptr %divdst, align 16216 %t1 = mul <4 x i32> %div, %y217 %t2 = sub <4 x i32> %x, %t1218 ret <4 x i32> %t2219}220 221define <2 x i64> @vector_i128_i64(<2 x i64> %x, <2 x i64> %y, ptr %divdst) nounwind {222; ALL-LABEL: vector_i128_i64:223; ALL: // %bb.0:224; ALL-NEXT: fmov x8, d1225; ALL-NEXT: fmov x9, d0226; ALL-NEXT: mov x10, v1.d[1]227; ALL-NEXT: mov x11, v0.d[1]228; ALL-NEXT: sdiv x9, x9, x8229; ALL-NEXT: sdiv x11, x11, x10230; ALL-NEXT: mul x8, x9, x8231; ALL-NEXT: fmov d2, x9232; ALL-NEXT: fmov d1, x8233; ALL-NEXT: mul x10, x11, x10234; ALL-NEXT: mov v2.d[1], x11235; ALL-NEXT: str q2, [x0]236; ALL-NEXT: mov v1.d[1], x10237; ALL-NEXT: sub v0.2d, v0.2d, v1.2d238; ALL-NEXT: ret239 %div = sdiv <2 x i64> %x, %y240 store <2 x i64> %div, ptr %divdst, align 16241 %t1 = mul <2 x i64> %div, %y242 %t2 = sub <2 x i64> %x, %t1243 ret <2 x i64> %t2244}245 246; Special tests.247 248define i32 @scalar_i32_commutative(i32 %x, ptr %ysrc, ptr %divdst) nounwind {249; ALL-LABEL: scalar_i32_commutative:250; ALL: // %bb.0:251; ALL-NEXT: ldr w8, [x1]252; ALL-NEXT: sdiv w9, w0, w8253; ALL-NEXT: msub w0, w8, w9, w0254; ALL-NEXT: str w9, [x2]255; ALL-NEXT: ret256 %y = load i32, ptr %ysrc, align 4257 %div = sdiv i32 %x, %y258 store i32 %div, ptr %divdst, align 4259 %t1 = mul i32 %y, %div ; commutative260 %t2 = sub i32 %x, %t1261 ret i32 %t2262}263 264; We do not care about extra uses.265define i32 @extrause(i32 %x, i32 %y, ptr %divdst, ptr %t1dst) nounwind {266; ALL-LABEL: extrause:267; ALL: // %bb.0:268; ALL-NEXT: sdiv w8, w0, w1269; ALL-NEXT: mul w9, w8, w1270; ALL-NEXT: str w8, [x2]271; ALL-NEXT: sub w0, w0, w9272; ALL-NEXT: str w9, [x3]273; ALL-NEXT: ret274 %div = sdiv i32 %x, %y275 store i32 %div, ptr %divdst, align 4276 %t1 = mul i32 %div, %y277 store i32 %t1, ptr %t1dst, align 4278 %t2 = sub i32 %x, %t1279 ret i32 %t2280}281 282; 'rem' should appear next to 'div'.283define i32 @multiple_bb(i32 %x, i32 %y, ptr %divdst, i1 zeroext %store_srem, ptr %sremdst) nounwind {284; ALL-LABEL: multiple_bb:285; ALL: // %bb.0:286; ALL-NEXT: mov w8, w0287; ALL-NEXT: sdiv w0, w0, w1288; ALL-NEXT: str w0, [x2]289; ALL-NEXT: cbz w3, .LBB10_2290; ALL-NEXT: // %bb.1: // %do_srem291; ALL-NEXT: msub w8, w0, w1, w8292; ALL-NEXT: str w8, [x4]293; ALL-NEXT: .LBB10_2: // %end294; ALL-NEXT: ret295 %div = sdiv i32 %x, %y296 store i32 %div, ptr %divdst, align 4297 br i1 %store_srem, label %do_srem, label %end298do_srem:299 %t1 = mul i32 %div, %y300 %t2 = sub i32 %x, %t1301 store i32 %t2, ptr %sremdst, align 4302 br label %end303end:304 ret i32 %div305}306 307define i32 @negative_different_x(i32 %x0, i32 %x1, i32 %y, ptr %divdst) nounwind {308; ALL-LABEL: negative_different_x:309; ALL: // %bb.0:310; ALL-NEXT: sdiv w8, w0, w2311; ALL-NEXT: msub w0, w8, w2, w1312; ALL-NEXT: str w8, [x3]313; ALL-NEXT: ret314 %div = sdiv i32 %x0, %y ; not %x1315 store i32 %div, ptr %divdst, align 4316 %t1 = mul i32 %div, %y317 %t2 = sub i32 %x1, %t1 ; not %x0318 ret i32 %t2319}320