1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=aarch64-- | FileCheck %s 3 4declare <1 x i8> @llvm.usub.sat.v1i8(<1 x i8>, <1 x i8>) 5declare <2 x i8> @llvm.usub.sat.v2i8(<2 x i8>, <2 x i8>) 6declare <4 x i8> @llvm.usub.sat.v4i8(<4 x i8>, <4 x i8>) 7declare <8 x i8> @llvm.usub.sat.v8i8(<8 x i8>, <8 x i8>) 8declare <12 x i8> @llvm.usub.sat.v12i8(<12 x i8>, <12 x i8>) 9declare <16 x i8> @llvm.usub.sat.v16i8(<16 x i8>, <16 x i8>) 10declare <32 x i8> @llvm.usub.sat.v32i8(<32 x i8>, <32 x i8>) 11declare <64 x i8> @llvm.usub.sat.v64i8(<64 x i8>, <64 x i8>) 12 13declare <1 x i16> @llvm.usub.sat.v1i16(<1 x i16>, <1 x i16>) 14declare <2 x i16> @llvm.usub.sat.v2i16(<2 x i16>, <2 x i16>) 15declare <4 x i16> @llvm.usub.sat.v4i16(<4 x i16>, <4 x i16>) 16declare <8 x i16> @llvm.usub.sat.v8i16(<8 x i16>, <8 x i16>) 17declare <12 x i16> @llvm.usub.sat.v12i16(<12 x i16>, <12 x i16>) 18declare <16 x i16> @llvm.usub.sat.v16i16(<16 x i16>, <16 x i16>) 19declare <32 x i16> @llvm.usub.sat.v32i16(<32 x i16>, <32 x i16>) 20 21declare <16 x i1> @llvm.usub.sat.v16i1(<16 x i1>, <16 x i1>) 22declare <16 x i4> @llvm.usub.sat.v16i4(<16 x i4>, <16 x i4>) 23 24declare <2 x i32> @llvm.usub.sat.v2i32(<2 x i32>, <2 x i32>) 25declare <4 x i32> @llvm.usub.sat.v4i32(<4 x i32>, <4 x i32>) 26declare <8 x i32> @llvm.usub.sat.v8i32(<8 x i32>, <8 x i32>) 27declare <16 x i32> @llvm.usub.sat.v16i32(<16 x i32>, <16 x i32>) 28declare <2 x i64> @llvm.usub.sat.v2i64(<2 x i64>, <2 x i64>) 29declare <4 x i64> @llvm.usub.sat.v4i64(<4 x i64>, <4 x i64>) 30declare <8 x i64> @llvm.usub.sat.v8i64(<8 x i64>, <8 x i64>) 31 32declare <4 x i24> @llvm.usub.sat.v4i24(<4 x i24>, <4 x i24>) 33declare <2 x i128> @llvm.usub.sat.v2i128(<2 x i128>, <2 x i128>) 34 35 36define <16 x i8> @v16i8(<16 x i8> %x, <16 x i8> %y) nounwind { 37; CHECK-LABEL: v16i8: 38; CHECK: // %bb.0: 39; CHECK-NEXT: uqsub v0.16b, v0.16b, v1.16b 40; CHECK-NEXT: ret 41 %z = call <16 x i8> @llvm.usub.sat.v16i8(<16 x i8> %x, <16 x i8> %y) 42 ret <16 x i8> %z 43} 44 45define <32 x i8> @v32i8(<32 x i8> %x, <32 x i8> %y) nounwind { 46; CHECK-LABEL: v32i8: 47; CHECK: // %bb.0: 48; CHECK-NEXT: uqsub v0.16b, v0.16b, v2.16b 49; CHECK-NEXT: uqsub v1.16b, v1.16b, v3.16b 50; CHECK-NEXT: ret 51 %z = call <32 x i8> @llvm.usub.sat.v32i8(<32 x i8> %x, <32 x i8> %y) 52 ret <32 x i8> %z 53} 54 55define <64 x i8> @v64i8(<64 x i8> %x, <64 x i8> %y) nounwind { 56; CHECK-LABEL: v64i8: 57; CHECK: // %bb.0: 58; CHECK-NEXT: uqsub v2.16b, v2.16b, v6.16b 59; CHECK-NEXT: uqsub v0.16b, v0.16b, v4.16b 60; CHECK-NEXT: uqsub v1.16b, v1.16b, v5.16b 61; CHECK-NEXT: uqsub v3.16b, v3.16b, v7.16b 62; CHECK-NEXT: ret 63 %z = call <64 x i8> @llvm.usub.sat.v64i8(<64 x i8> %x, <64 x i8> %y) 64 ret <64 x i8> %z 65} 66 67define <8 x i16> @v8i16(<8 x i16> %x, <8 x i16> %y) nounwind { 68; CHECK-LABEL: v8i16: 69; CHECK: // %bb.0: 70; CHECK-NEXT: uqsub v0.8h, v0.8h, v1.8h 71; CHECK-NEXT: ret 72 %z = call <8 x i16> @llvm.usub.sat.v8i16(<8 x i16> %x, <8 x i16> %y) 73 ret <8 x i16> %z 74} 75 76define <16 x i16> @v16i16(<16 x i16> %x, <16 x i16> %y) nounwind { 77; CHECK-LABEL: v16i16: 78; CHECK: // %bb.0: 79; CHECK-NEXT: uqsub v0.8h, v0.8h, v2.8h 80; CHECK-NEXT: uqsub v1.8h, v1.8h, v3.8h 81; CHECK-NEXT: ret 82 %z = call <16 x i16> @llvm.usub.sat.v16i16(<16 x i16> %x, <16 x i16> %y) 83 ret <16 x i16> %z 84} 85 86define <32 x i16> @v32i16(<32 x i16> %x, <32 x i16> %y) nounwind { 87; CHECK-LABEL: v32i16: 88; CHECK: // %bb.0: 89; CHECK-NEXT: uqsub v2.8h, v2.8h, v6.8h 90; CHECK-NEXT: uqsub v0.8h, v0.8h, v4.8h 91; CHECK-NEXT: uqsub v1.8h, v1.8h, v5.8h 92; CHECK-NEXT: uqsub v3.8h, v3.8h, v7.8h 93; CHECK-NEXT: ret 94 %z = call <32 x i16> @llvm.usub.sat.v32i16(<32 x i16> %x, <32 x i16> %y) 95 ret <32 x i16> %z 96} 97 98define void @v8i8(<8 x i8>* %px, <8 x i8>* %py, <8 x i8>* %pz) nounwind { 99; CHECK-LABEL: v8i8: 100; CHECK: // %bb.0: 101; CHECK-NEXT: ldr d0, [x1] 102; CHECK-NEXT: ldr d1, [x0] 103; CHECK-NEXT: uqsub v0.8b, v1.8b, v0.8b 104; CHECK-NEXT: str d0, [x2] 105; CHECK-NEXT: ret 106 %x = load <8 x i8>, <8 x i8>* %px 107 %y = load <8 x i8>, <8 x i8>* %py 108 %z = call <8 x i8> @llvm.usub.sat.v8i8(<8 x i8> %x, <8 x i8> %y) 109 store <8 x i8> %z, <8 x i8>* %pz 110 ret void 111} 112 113define void @v4i8(<4 x i8>* %px, <4 x i8>* %py, <4 x i8>* %pz) nounwind { 114; CHECK-LABEL: v4i8: 115; CHECK: // %bb.0: 116; CHECK-NEXT: ldr s0, [x0] 117; CHECK-NEXT: ldr s1, [x1] 118; CHECK-NEXT: ushll v0.8h, v0.8b, #0 119; CHECK-NEXT: ushll v1.8h, v1.8b, #0 120; CHECK-NEXT: uqsub v0.4h, v0.4h, v1.4h 121; CHECK-NEXT: xtn v0.8b, v0.8h 122; CHECK-NEXT: str s0, [x2] 123; CHECK-NEXT: ret 124 %x = load <4 x i8>, <4 x i8>* %px 125 %y = load <4 x i8>, <4 x i8>* %py 126 %z = call <4 x i8> @llvm.usub.sat.v4i8(<4 x i8> %x, <4 x i8> %y) 127 store <4 x i8> %z, <4 x i8>* %pz 128 ret void 129} 130 131define void @v2i8(<2 x i8>* %px, <2 x i8>* %py, <2 x i8>* %pz) nounwind { 132; CHECK-LABEL: v2i8: 133; CHECK: // %bb.0: 134; CHECK-NEXT: ldrb w8, [x1] 135; CHECK-NEXT: ldrb w9, [x0] 136; CHECK-NEXT: ldrb w10, [x1, #1] 137; CHECK-NEXT: fmov s1, w8 138; CHECK-NEXT: fmov s0, w9 139; CHECK-NEXT: ldrb w9, [x0, #1] 140; CHECK-NEXT: mov v1.s[1], w10 141; CHECK-NEXT: mov v0.s[1], w9 142; CHECK-NEXT: uqsub v0.2s, v0.2s, v1.2s 143; CHECK-NEXT: mov w8, v0.s[1] 144; CHECK-NEXT: fmov w9, s0 145; CHECK-NEXT: strb w9, [x2] 146; CHECK-NEXT: strb w8, [x2, #1] 147; CHECK-NEXT: ret 148 %x = load <2 x i8>, <2 x i8>* %px 149 %y = load <2 x i8>, <2 x i8>* %py 150 %z = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %x, <2 x i8> %y) 151 store <2 x i8> %z, <2 x i8>* %pz 152 ret void 153} 154 155define void @v4i16(<4 x i16>* %px, <4 x i16>* %py, <4 x i16>* %pz) nounwind { 156; CHECK-LABEL: v4i16: 157; CHECK: // %bb.0: 158; CHECK-NEXT: ldr d0, [x1] 159; CHECK-NEXT: ldr d1, [x0] 160; CHECK-NEXT: uqsub v0.4h, v1.4h, v0.4h 161; CHECK-NEXT: str d0, [x2] 162; CHECK-NEXT: ret 163 %x = load <4 x i16>, <4 x i16>* %px 164 %y = load <4 x i16>, <4 x i16>* %py 165 %z = call <4 x i16> @llvm.usub.sat.v4i16(<4 x i16> %x, <4 x i16> %y) 166 store <4 x i16> %z, <4 x i16>* %pz 167 ret void 168} 169 170define void @v2i16(<2 x i16>* %px, <2 x i16>* %py, <2 x i16>* %pz) nounwind { 171; CHECK-LABEL: v2i16: 172; CHECK: // %bb.0: 173; CHECK-NEXT: ldrh w8, [x1] 174; CHECK-NEXT: ldrh w9, [x0] 175; CHECK-NEXT: ldrh w10, [x1, #2] 176; CHECK-NEXT: fmov s1, w8 177; CHECK-NEXT: fmov s0, w9 178; CHECK-NEXT: ldrh w9, [x0, #2] 179; CHECK-NEXT: mov v1.s[1], w10 180; CHECK-NEXT: mov v0.s[1], w9 181; CHECK-NEXT: uqsub v0.2s, v0.2s, v1.2s 182; CHECK-NEXT: mov w8, v0.s[1] 183; CHECK-NEXT: fmov w9, s0 184; CHECK-NEXT: strh w9, [x2] 185; CHECK-NEXT: strh w8, [x2, #2] 186; CHECK-NEXT: ret 187 %x = load <2 x i16>, <2 x i16>* %px 188 %y = load <2 x i16>, <2 x i16>* %py 189 %z = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> %x, <2 x i16> %y) 190 store <2 x i16> %z, <2 x i16>* %pz 191 ret void 192} 193 194define <12 x i8> @v12i8(<12 x i8> %x, <12 x i8> %y) nounwind { 195; CHECK-LABEL: v12i8: 196; CHECK: // %bb.0: 197; CHECK-NEXT: uqsub v0.16b, v0.16b, v1.16b 198; CHECK-NEXT: ret 199 %z = call <12 x i8> @llvm.usub.sat.v12i8(<12 x i8> %x, <12 x i8> %y) 200 ret <12 x i8> %z 201} 202 203define void @v12i16(<12 x i16>* %px, <12 x i16>* %py, <12 x i16>* %pz) nounwind { 204; CHECK-LABEL: v12i16: 205; CHECK: // %bb.0: 206; CHECK-NEXT: ldp q0, q3, [x1] 207; CHECK-NEXT: ldp q1, q2, [x0] 208; CHECK-NEXT: uqsub v0.8h, v1.8h, v0.8h 209; CHECK-NEXT: uqsub v1.8h, v2.8h, v3.8h 210; CHECK-NEXT: str q0, [x2] 211; CHECK-NEXT: str d1, [x2, #16] 212; CHECK-NEXT: ret 213 %x = load <12 x i16>, <12 x i16>* %px 214 %y = load <12 x i16>, <12 x i16>* %py 215 %z = call <12 x i16> @llvm.usub.sat.v12i16(<12 x i16> %x, <12 x i16> %y) 216 store <12 x i16> %z, <12 x i16>* %pz 217 ret void 218} 219 220define void @v1i8(<1 x i8>* %px, <1 x i8>* %py, <1 x i8>* %pz) nounwind { 221; CHECK-LABEL: v1i8: 222; CHECK: // %bb.0: 223; CHECK-NEXT: ldr b0, [x1] 224; CHECK-NEXT: ldr b1, [x0] 225; CHECK-NEXT: uqsub v0.8b, v1.8b, v0.8b 226; CHECK-NEXT: st1 { v0.b }[0], [x2] 227; CHECK-NEXT: ret 228 %x = load <1 x i8>, <1 x i8>* %px 229 %y = load <1 x i8>, <1 x i8>* %py 230 %z = call <1 x i8> @llvm.usub.sat.v1i8(<1 x i8> %x, <1 x i8> %y) 231 store <1 x i8> %z, <1 x i8>* %pz 232 ret void 233} 234 235define void @v1i16(<1 x i16>* %px, <1 x i16>* %py, <1 x i16>* %pz) nounwind { 236; CHECK-LABEL: v1i16: 237; CHECK: // %bb.0: 238; CHECK-NEXT: ldr h0, [x1] 239; CHECK-NEXT: ldr h1, [x0] 240; CHECK-NEXT: uqsub v0.4h, v1.4h, v0.4h 241; CHECK-NEXT: str h0, [x2] 242; CHECK-NEXT: ret 243 %x = load <1 x i16>, <1 x i16>* %px 244 %y = load <1 x i16>, <1 x i16>* %py 245 %z = call <1 x i16> @llvm.usub.sat.v1i16(<1 x i16> %x, <1 x i16> %y) 246 store <1 x i16> %z, <1 x i16>* %pz 247 ret void 248} 249 250define <16 x i4> @v16i4(<16 x i4> %x, <16 x i4> %y) nounwind { 251; CHECK-LABEL: v16i4: 252; CHECK: // %bb.0: 253; CHECK-NEXT: movi v2.16b, #15 254; CHECK-NEXT: and v1.16b, v1.16b, v2.16b 255; CHECK-NEXT: and v0.16b, v0.16b, v2.16b 256; CHECK-NEXT: uqsub v0.16b, v0.16b, v1.16b 257; CHECK-NEXT: ret 258 %z = call <16 x i4> @llvm.usub.sat.v16i4(<16 x i4> %x, <16 x i4> %y) 259 ret <16 x i4> %z 260} 261 262define <16 x i1> @v16i1(<16 x i1> %x, <16 x i1> %y) nounwind { 263; CHECK-LABEL: v16i1: 264; CHECK: // %bb.0: 265; CHECK-NEXT: movi v2.16b, #1 266; CHECK-NEXT: eor v1.16b, v1.16b, v2.16b 267; CHECK-NEXT: and v0.16b, v0.16b, v1.16b 268; CHECK-NEXT: ret 269 %z = call <16 x i1> @llvm.usub.sat.v16i1(<16 x i1> %x, <16 x i1> %y) 270 ret <16 x i1> %z 271} 272 273define <2 x i32> @v2i32(<2 x i32> %x, <2 x i32> %y) nounwind { 274; CHECK-LABEL: v2i32: 275; CHECK: // %bb.0: 276; CHECK-NEXT: uqsub v0.2s, v0.2s, v1.2s 277; CHECK-NEXT: ret 278 %z = call <2 x i32> @llvm.usub.sat.v2i32(<2 x i32> %x, <2 x i32> %y) 279 ret <2 x i32> %z 280} 281 282define <4 x i32> @v4i32(<4 x i32> %x, <4 x i32> %y) nounwind { 283; CHECK-LABEL: v4i32: 284; CHECK: // %bb.0: 285; CHECK-NEXT: uqsub v0.4s, v0.4s, v1.4s 286; CHECK-NEXT: ret 287 %z = call <4 x i32> @llvm.usub.sat.v4i32(<4 x i32> %x, <4 x i32> %y) 288 ret <4 x i32> %z 289} 290 291define <8 x i32> @v8i32(<8 x i32> %x, <8 x i32> %y) nounwind { 292; CHECK-LABEL: v8i32: 293; CHECK: // %bb.0: 294; CHECK-NEXT: uqsub v0.4s, v0.4s, v2.4s 295; CHECK-NEXT: uqsub v1.4s, v1.4s, v3.4s 296; CHECK-NEXT: ret 297 %z = call <8 x i32> @llvm.usub.sat.v8i32(<8 x i32> %x, <8 x i32> %y) 298 ret <8 x i32> %z 299} 300 301define <16 x i32> @v16i32(<16 x i32> %x, <16 x i32> %y) nounwind { 302; CHECK-LABEL: v16i32: 303; CHECK: // %bb.0: 304; CHECK-NEXT: uqsub v2.4s, v2.4s, v6.4s 305; CHECK-NEXT: uqsub v0.4s, v0.4s, v4.4s 306; CHECK-NEXT: uqsub v1.4s, v1.4s, v5.4s 307; CHECK-NEXT: uqsub v3.4s, v3.4s, v7.4s 308; CHECK-NEXT: ret 309 %z = call <16 x i32> @llvm.usub.sat.v16i32(<16 x i32> %x, <16 x i32> %y) 310 ret <16 x i32> %z 311} 312 313define <2 x i64> @v2i64(<2 x i64> %x, <2 x i64> %y) nounwind { 314; CHECK-LABEL: v2i64: 315; CHECK: // %bb.0: 316; CHECK-NEXT: uqsub v0.2d, v0.2d, v1.2d 317; CHECK-NEXT: ret 318 %z = call <2 x i64> @llvm.usub.sat.v2i64(<2 x i64> %x, <2 x i64> %y) 319 ret <2 x i64> %z 320} 321 322define <4 x i64> @v4i64(<4 x i64> %x, <4 x i64> %y) nounwind { 323; CHECK-LABEL: v4i64: 324; CHECK: // %bb.0: 325; CHECK-NEXT: uqsub v0.2d, v0.2d, v2.2d 326; CHECK-NEXT: uqsub v1.2d, v1.2d, v3.2d 327; CHECK-NEXT: ret 328 %z = call <4 x i64> @llvm.usub.sat.v4i64(<4 x i64> %x, <4 x i64> %y) 329 ret <4 x i64> %z 330} 331 332define <8 x i64> @v8i64(<8 x i64> %x, <8 x i64> %y) nounwind { 333; CHECK-LABEL: v8i64: 334; CHECK: // %bb.0: 335; CHECK-NEXT: uqsub v2.2d, v2.2d, v6.2d 336; CHECK-NEXT: uqsub v0.2d, v0.2d, v4.2d 337; CHECK-NEXT: uqsub v1.2d, v1.2d, v5.2d 338; CHECK-NEXT: uqsub v3.2d, v3.2d, v7.2d 339; CHECK-NEXT: ret 340 %z = call <8 x i64> @llvm.usub.sat.v8i64(<8 x i64> %x, <8 x i64> %y) 341 ret <8 x i64> %z 342} 343 344define <2 x i128> @v2i128(<2 x i128> %x, <2 x i128> %y) nounwind { 345; CHECK-LABEL: v2i128: 346; CHECK: // %bb.0: 347; CHECK-NEXT: subs x8, x2, x6 348; CHECK-NEXT: sbcs x9, x3, x7 349; CHECK-NEXT: cset w10, lo 350; CHECK-NEXT: cmp w10, #0 351; CHECK-NEXT: csel x2, xzr, x8, ne 352; CHECK-NEXT: csel x3, xzr, x9, ne 353; CHECK-NEXT: subs x8, x0, x4 354; CHECK-NEXT: sbcs x9, x1, x5 355; CHECK-NEXT: cset w10, lo 356; CHECK-NEXT: cmp w10, #0 357; CHECK-NEXT: csel x8, xzr, x8, ne 358; CHECK-NEXT: csel x1, xzr, x9, ne 359; CHECK-NEXT: fmov d0, x8 360; CHECK-NEXT: mov v0.d[1], x1 361; CHECK-NEXT: fmov x0, d0 362; CHECK-NEXT: ret 363 %z = call <2 x i128> @llvm.usub.sat.v2i128(<2 x i128> %x, <2 x i128> %y) 364 ret <2 x i128> %z 365} 366