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 v0.16b, v0.16b, v4.16b 59; CHECK-NEXT: uqsub v1.16b, v1.16b, v5.16b 60; CHECK-NEXT: uqsub v2.16b, v2.16b, v6.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 v0.8h, v0.8h, v4.8h 90; CHECK-NEXT: uqsub v1.8h, v1.8h, v5.8h 91; CHECK-NEXT: uqsub v2.8h, v2.8h, v6.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, [x0] 102; CHECK-NEXT: ldr d1, [x1] 103; CHECK-NEXT: uqsub v0.8b, v0.8b, v1.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: ldrb w8, [x0] 117; CHECK-NEXT: ldrb w9, [x1] 118; CHECK-NEXT: ldrb w10, [x0, #1] 119; CHECK-NEXT: ldrb w11, [x1, #1] 120; CHECK-NEXT: fmov s0, w8 121; CHECK-NEXT: fmov s1, w9 122; CHECK-NEXT: ldrb w8, [x0, #2] 123; CHECK-NEXT: ldrb w9, [x1, #2] 124; CHECK-NEXT: mov v0.h[1], w10 125; CHECK-NEXT: mov v1.h[1], w11 126; CHECK-NEXT: ldrb w10, [x0, #3] 127; CHECK-NEXT: ldrb w11, [x1, #3] 128; CHECK-NEXT: mov v0.h[2], w8 129; CHECK-NEXT: mov v1.h[2], w9 130; CHECK-NEXT: mov v0.h[3], w10 131; CHECK-NEXT: mov v1.h[3], w11 132; CHECK-NEXT: uqsub v0.4h, v0.4h, v1.4h 133; CHECK-NEXT: xtn v0.8b, v0.8h 134; CHECK-NEXT: str s0, [x2] 135; CHECK-NEXT: ret 136 %x = load <4 x i8>, <4 x i8>* %px 137 %y = load <4 x i8>, <4 x i8>* %py 138 %z = call <4 x i8> @llvm.usub.sat.v4i8(<4 x i8> %x, <4 x i8> %y) 139 store <4 x i8> %z, <4 x i8>* %pz 140 ret void 141} 142 143define void @v2i8(<2 x i8>* %px, <2 x i8>* %py, <2 x i8>* %pz) nounwind { 144; CHECK-LABEL: v2i8: 145; CHECK: // %bb.0: 146; CHECK-NEXT: ldrb w8, [x0] 147; CHECK-NEXT: ldrb w9, [x1] 148; CHECK-NEXT: ldrb w10, [x0, #1] 149; CHECK-NEXT: ldrb w11, [x1, #1] 150; CHECK-NEXT: fmov s0, w8 151; CHECK-NEXT: fmov s1, w9 152; CHECK-NEXT: mov v0.s[1], w10 153; CHECK-NEXT: mov v1.s[1], w11 154; CHECK-NEXT: uqsub v0.2s, v0.2s, v1.2s 155; CHECK-NEXT: mov w8, v0.s[1] 156; CHECK-NEXT: fmov w9, s0 157; CHECK-NEXT: strb w9, [x2] 158; CHECK-NEXT: strb w8, [x2, #1] 159; CHECK-NEXT: ret 160 %x = load <2 x i8>, <2 x i8>* %px 161 %y = load <2 x i8>, <2 x i8>* %py 162 %z = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %x, <2 x i8> %y) 163 store <2 x i8> %z, <2 x i8>* %pz 164 ret void 165} 166 167define void @v4i16(<4 x i16>* %px, <4 x i16>* %py, <4 x i16>* %pz) nounwind { 168; CHECK-LABEL: v4i16: 169; CHECK: // %bb.0: 170; CHECK-NEXT: ldr d0, [x0] 171; CHECK-NEXT: ldr d1, [x1] 172; CHECK-NEXT: uqsub v0.4h, v0.4h, v1.4h 173; CHECK-NEXT: str d0, [x2] 174; CHECK-NEXT: ret 175 %x = load <4 x i16>, <4 x i16>* %px 176 %y = load <4 x i16>, <4 x i16>* %py 177 %z = call <4 x i16> @llvm.usub.sat.v4i16(<4 x i16> %x, <4 x i16> %y) 178 store <4 x i16> %z, <4 x i16>* %pz 179 ret void 180} 181 182define void @v2i16(<2 x i16>* %px, <2 x i16>* %py, <2 x i16>* %pz) nounwind { 183; CHECK-LABEL: v2i16: 184; CHECK: // %bb.0: 185; CHECK-NEXT: ldrh w8, [x0] 186; CHECK-NEXT: ldrh w9, [x1] 187; CHECK-NEXT: ldrh w10, [x0, #2] 188; CHECK-NEXT: ldrh w11, [x1, #2] 189; CHECK-NEXT: fmov s0, w8 190; CHECK-NEXT: fmov s1, w9 191; CHECK-NEXT: mov v0.s[1], w10 192; CHECK-NEXT: mov v1.s[1], w11 193; CHECK-NEXT: uqsub v0.2s, v0.2s, v1.2s 194; CHECK-NEXT: mov w8, v0.s[1] 195; CHECK-NEXT: fmov w9, s0 196; CHECK-NEXT: strh w9, [x2] 197; CHECK-NEXT: strh w8, [x2, #2] 198; CHECK-NEXT: ret 199 %x = load <2 x i16>, <2 x i16>* %px 200 %y = load <2 x i16>, <2 x i16>* %py 201 %z = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> %x, <2 x i16> %y) 202 store <2 x i16> %z, <2 x i16>* %pz 203 ret void 204} 205 206define <12 x i8> @v12i8(<12 x i8> %x, <12 x i8> %y) nounwind { 207; CHECK-LABEL: v12i8: 208; CHECK: // %bb.0: 209; CHECK-NEXT: uqsub v0.16b, v0.16b, v1.16b 210; CHECK-NEXT: ret 211 %z = call <12 x i8> @llvm.usub.sat.v12i8(<12 x i8> %x, <12 x i8> %y) 212 ret <12 x i8> %z 213} 214 215define void @v12i16(<12 x i16>* %px, <12 x i16>* %py, <12 x i16>* %pz) nounwind { 216; CHECK-LABEL: v12i16: 217; CHECK: // %bb.0: 218; CHECK-NEXT: ldp q0, q1, [x0] 219; CHECK-NEXT: ldp q3, q2, [x1] 220; CHECK-NEXT: uqsub v1.8h, v1.8h, v2.8h 221; CHECK-NEXT: uqsub v0.8h, v0.8h, v3.8h 222; CHECK-NEXT: str q0, [x2] 223; CHECK-NEXT: str d1, [x2, #16] 224; CHECK-NEXT: ret 225 %x = load <12 x i16>, <12 x i16>* %px 226 %y = load <12 x i16>, <12 x i16>* %py 227 %z = call <12 x i16> @llvm.usub.sat.v12i16(<12 x i16> %x, <12 x i16> %y) 228 store <12 x i16> %z, <12 x i16>* %pz 229 ret void 230} 231 232define void @v1i8(<1 x i8>* %px, <1 x i8>* %py, <1 x i8>* %pz) nounwind { 233; CHECK-LABEL: v1i8: 234; CHECK: // %bb.0: 235; CHECK-NEXT: ldr b0, [x0] 236; CHECK-NEXT: ldr b1, [x1] 237; CHECK-NEXT: uqsub v0.8b, v0.8b, v1.8b 238; CHECK-NEXT: st1 { v0.b }[0], [x2] 239; CHECK-NEXT: ret 240 %x = load <1 x i8>, <1 x i8>* %px 241 %y = load <1 x i8>, <1 x i8>* %py 242 %z = call <1 x i8> @llvm.usub.sat.v1i8(<1 x i8> %x, <1 x i8> %y) 243 store <1 x i8> %z, <1 x i8>* %pz 244 ret void 245} 246 247define void @v1i16(<1 x i16>* %px, <1 x i16>* %py, <1 x i16>* %pz) nounwind { 248; CHECK-LABEL: v1i16: 249; CHECK: // %bb.0: 250; CHECK-NEXT: ldr h0, [x0] 251; CHECK-NEXT: ldr h1, [x1] 252; CHECK-NEXT: uqsub v0.4h, v0.4h, v1.4h 253; CHECK-NEXT: str h0, [x2] 254; CHECK-NEXT: ret 255 %x = load <1 x i16>, <1 x i16>* %px 256 %y = load <1 x i16>, <1 x i16>* %py 257 %z = call <1 x i16> @llvm.usub.sat.v1i16(<1 x i16> %x, <1 x i16> %y) 258 store <1 x i16> %z, <1 x i16>* %pz 259 ret void 260} 261 262define <16 x i4> @v16i4(<16 x i4> %x, <16 x i4> %y) nounwind { 263; CHECK-LABEL: v16i4: 264; CHECK: // %bb.0: 265; CHECK-NEXT: movi v2.16b, #15 266; CHECK-NEXT: and v1.16b, v1.16b, v2.16b 267; CHECK-NEXT: and v0.16b, v0.16b, v2.16b 268; CHECK-NEXT: uqsub v0.16b, v0.16b, v1.16b 269; CHECK-NEXT: ret 270 %z = call <16 x i4> @llvm.usub.sat.v16i4(<16 x i4> %x, <16 x i4> %y) 271 ret <16 x i4> %z 272} 273 274define <16 x i1> @v16i1(<16 x i1> %x, <16 x i1> %y) nounwind { 275; CHECK-LABEL: v16i1: 276; CHECK: // %bb.0: 277; CHECK-NEXT: movi v2.16b, #1 278; CHECK-NEXT: eor v1.16b, v1.16b, v2.16b 279; CHECK-NEXT: and v0.16b, v0.16b, v1.16b 280; CHECK-NEXT: ret 281 %z = call <16 x i1> @llvm.usub.sat.v16i1(<16 x i1> %x, <16 x i1> %y) 282 ret <16 x i1> %z 283} 284 285define <2 x i32> @v2i32(<2 x i32> %x, <2 x i32> %y) nounwind { 286; CHECK-LABEL: v2i32: 287; CHECK: // %bb.0: 288; CHECK-NEXT: uqsub v0.2s, v0.2s, v1.2s 289; CHECK-NEXT: ret 290 %z = call <2 x i32> @llvm.usub.sat.v2i32(<2 x i32> %x, <2 x i32> %y) 291 ret <2 x i32> %z 292} 293 294define <4 x i32> @v4i32(<4 x i32> %x, <4 x i32> %y) nounwind { 295; CHECK-LABEL: v4i32: 296; CHECK: // %bb.0: 297; CHECK-NEXT: uqsub v0.4s, v0.4s, v1.4s 298; CHECK-NEXT: ret 299 %z = call <4 x i32> @llvm.usub.sat.v4i32(<4 x i32> %x, <4 x i32> %y) 300 ret <4 x i32> %z 301} 302 303define <8 x i32> @v8i32(<8 x i32> %x, <8 x i32> %y) nounwind { 304; CHECK-LABEL: v8i32: 305; CHECK: // %bb.0: 306; CHECK-NEXT: uqsub v0.4s, v0.4s, v2.4s 307; CHECK-NEXT: uqsub v1.4s, v1.4s, v3.4s 308; CHECK-NEXT: ret 309 %z = call <8 x i32> @llvm.usub.sat.v8i32(<8 x i32> %x, <8 x i32> %y) 310 ret <8 x i32> %z 311} 312 313define <16 x i32> @v16i32(<16 x i32> %x, <16 x i32> %y) nounwind { 314; CHECK-LABEL: v16i32: 315; CHECK: // %bb.0: 316; CHECK-NEXT: uqsub v0.4s, v0.4s, v4.4s 317; CHECK-NEXT: uqsub v1.4s, v1.4s, v5.4s 318; CHECK-NEXT: uqsub v2.4s, v2.4s, v6.4s 319; CHECK-NEXT: uqsub v3.4s, v3.4s, v7.4s 320; CHECK-NEXT: ret 321 %z = call <16 x i32> @llvm.usub.sat.v16i32(<16 x i32> %x, <16 x i32> %y) 322 ret <16 x i32> %z 323} 324 325define <2 x i64> @v2i64(<2 x i64> %x, <2 x i64> %y) nounwind { 326; CHECK-LABEL: v2i64: 327; CHECK: // %bb.0: 328; CHECK-NEXT: uqsub v0.2d, v0.2d, v1.2d 329; CHECK-NEXT: ret 330 %z = call <2 x i64> @llvm.usub.sat.v2i64(<2 x i64> %x, <2 x i64> %y) 331 ret <2 x i64> %z 332} 333 334define <4 x i64> @v4i64(<4 x i64> %x, <4 x i64> %y) nounwind { 335; CHECK-LABEL: v4i64: 336; CHECK: // %bb.0: 337; CHECK-NEXT: uqsub v0.2d, v0.2d, v2.2d 338; CHECK-NEXT: uqsub v1.2d, v1.2d, v3.2d 339; CHECK-NEXT: ret 340 %z = call <4 x i64> @llvm.usub.sat.v4i64(<4 x i64> %x, <4 x i64> %y) 341 ret <4 x i64> %z 342} 343 344define <8 x i64> @v8i64(<8 x i64> %x, <8 x i64> %y) nounwind { 345; CHECK-LABEL: v8i64: 346; CHECK: // %bb.0: 347; CHECK-NEXT: uqsub v0.2d, v0.2d, v4.2d 348; CHECK-NEXT: uqsub v1.2d, v1.2d, v5.2d 349; CHECK-NEXT: uqsub v2.2d, v2.2d, v6.2d 350; CHECK-NEXT: uqsub v3.2d, v3.2d, v7.2d 351; CHECK-NEXT: ret 352 %z = call <8 x i64> @llvm.usub.sat.v8i64(<8 x i64> %x, <8 x i64> %y) 353 ret <8 x i64> %z 354} 355 356define <2 x i128> @v2i128(<2 x i128> %x, <2 x i128> %y) nounwind { 357; CHECK-LABEL: v2i128: 358; CHECK: // %bb.0: 359; CHECK-NEXT: subs x8, x2, x6 360; CHECK-NEXT: sbcs x9, x3, x7 361; CHECK-NEXT: cmp x8, x2 362; CHECK-NEXT: cset w10, hi 363; CHECK-NEXT: cmp x9, x3 364; CHECK-NEXT: cset w11, hi 365; CHECK-NEXT: csel w10, w10, w11, eq 366; CHECK-NEXT: cmp w10, #0 // =0 367; CHECK-NEXT: csel x3, xzr, x9, ne 368; CHECK-NEXT: csel x2, xzr, x8, ne 369; CHECK-NEXT: subs x8, x0, x4 370; CHECK-NEXT: sbcs x9, x1, x5 371; CHECK-NEXT: cmp x8, x0 372; CHECK-NEXT: cset w10, hi 373; CHECK-NEXT: cmp x9, x1 374; CHECK-NEXT: cset w11, hi 375; CHECK-NEXT: csel w10, w10, w11, eq 376; CHECK-NEXT: cmp w10, #0 // =0 377; CHECK-NEXT: csel x8, xzr, x8, ne 378; CHECK-NEXT: csel x1, xzr, x9, ne 379; CHECK-NEXT: fmov d0, x8 380; CHECK-NEXT: mov v0.d[1], x1 381; CHECK-NEXT: fmov x0, d0 382; CHECK-NEXT: ret 383 %z = call <2 x i128> @llvm.usub.sat.v2i128(<2 x i128> %x, <2 x i128> %y) 384 ret <2 x i128> %z 385} 386