1; RUN: llc < %s -mtriple=arm64-eabi -aarch64-neon-syntax=apple -asm-verbose=false -mcpu=cyclone | FileCheck %s 2 3define signext i8 @test_vaddv_s8(<8 x i8> %a1) { 4; CHECK-LABEL: test_vaddv_s8: 5; CHECK: addv.8b b[[REGNUM:[0-9]+]], v0 6; CHECK-NEXT: smov.b w0, v[[REGNUM]][0] 7; CHECK-NEXT: ret 8entry: 9 %vaddv.i = tail call i32 @llvm.aarch64.neon.saddv.i32.v8i8(<8 x i8> %a1) 10 %0 = trunc i32 %vaddv.i to i8 11 ret i8 %0 12} 13 14define <8 x i8> @test_vaddv_s8_used_by_laneop(<8 x i8> %a1, <8 x i8> %a2) { 15; CHECK-LABEL: test_vaddv_s8_used_by_laneop: 16; CHECK: addv.8b b[[REGNUM:[0-9]+]], v1 17; CHECK-NEXT: mov.b v0[3], v[[REGNUM]][0] 18; CHECK-NEXT: ret 19entry: 20 %0 = tail call i32 @llvm.aarch64.neon.saddv.i32.v8i8(<8 x i8> %a2) 21 %1 = trunc i32 %0 to i8 22 %2 = insertelement <8 x i8> %a1, i8 %1, i32 3 23 ret <8 x i8> %2 24} 25 26define signext i16 @test_vaddv_s16(<4 x i16> %a1) { 27; CHECK-LABEL: test_vaddv_s16: 28; CHECK: addv.4h h[[REGNUM:[0-9]+]], v0 29; CHECK-NEXT: smov.h w0, v[[REGNUM]][0] 30; CHECK-NEXT: ret 31entry: 32 %vaddv.i = tail call i32 @llvm.aarch64.neon.saddv.i32.v4i16(<4 x i16> %a1) 33 %0 = trunc i32 %vaddv.i to i16 34 ret i16 %0 35} 36 37define <4 x i16> @test_vaddv_s16_used_by_laneop(<4 x i16> %a1, <4 x i16> %a2) { 38; CHECK-LABEL: test_vaddv_s16_used_by_laneop: 39; CHECK: addv.4h h[[REGNUM:[0-9]+]], v1 40; CHECK-NEXT: mov.h v0[3], v[[REGNUM]][0] 41; CHECK-NEXT: ret 42entry: 43 %0 = tail call i32 @llvm.aarch64.neon.saddv.i32.v4i16(<4 x i16> %a2) 44 %1 = trunc i32 %0 to i16 45 %2 = insertelement <4 x i16> %a1, i16 %1, i32 3 46 ret <4 x i16> %2 47} 48 49define i32 @test_vaddv_s32(<2 x i32> %a1) { 50; CHECK-LABEL: test_vaddv_s32: 51; 2 x i32 is not supported by the ISA, thus, this is a special case 52; CHECK: addp.2s v[[REGNUM:[0-9]+]], v0, v0 53; CHECK-NEXT: fmov w0, s[[REGNUM]] 54; CHECK-NEXT: ret 55entry: 56 %vaddv.i = tail call i32 @llvm.aarch64.neon.saddv.i32.v2i32(<2 x i32> %a1) 57 ret i32 %vaddv.i 58} 59 60define <2 x i32> @test_vaddv_s32_used_by_laneop(<2 x i32> %a1, <2 x i32> %a2) { 61; CHECK-LABEL: test_vaddv_s32_used_by_laneop: 62; CHECK: addp.2s v[[REGNUM:[0-9]+]], v1, v1 63; CHECK-NEXT: mov.s v0[1], v[[REGNUM]][0] 64; CHECK-NEXT: ret 65entry: 66 %0 = tail call i32 @llvm.aarch64.neon.saddv.i32.v2i32(<2 x i32> %a2) 67 %1 = insertelement <2 x i32> %a1, i32 %0, i32 1 68 ret <2 x i32> %1 69} 70 71define i64 @test_vaddv_s64(<2 x i64> %a1) { 72; CHECK-LABEL: test_vaddv_s64: 73; CHECK: addp.2d [[REGNUM:d[0-9]+]], v0 74; CHECK-NEXT: fmov x0, [[REGNUM]] 75; CHECK-NEXT: ret 76entry: 77 %vaddv.i = tail call i64 @llvm.aarch64.neon.saddv.i64.v2i64(<2 x i64> %a1) 78 ret i64 %vaddv.i 79} 80 81define <2 x i64> @test_vaddv_s64_used_by_laneop(<2 x i64> %a1, <2 x i64> %a2) { 82; CHECK-LABEL: test_vaddv_s64_used_by_laneop: 83; CHECK: addp.2d d[[REGNUM:[0-9]+]], v1 84; CHECK-NEXT: mov.d v0[1], v[[REGNUM]][0] 85; CHECK-NEXT: ret 86entry: 87 %0 = tail call i64 @llvm.aarch64.neon.saddv.i64.v2i64(<2 x i64> %a2) 88 %1 = insertelement <2 x i64> %a1, i64 %0, i64 1 89 ret <2 x i64> %1 90} 91 92define zeroext i8 @test_vaddv_u8(<8 x i8> %a1) { 93; CHECK-LABEL: test_vaddv_u8: 94; CHECK: addv.8b b[[REGNUM:[0-9]+]], v0 95; CHECK-NEXT: fmov w0, s[[REGNUM]] 96; CHECK-NEXT: ret 97entry: 98 %vaddv.i = tail call i32 @llvm.aarch64.neon.uaddv.i32.v8i8(<8 x i8> %a1) 99 %0 = trunc i32 %vaddv.i to i8 100 ret i8 %0 101} 102 103define <8 x i8> @test_vaddv_u8_used_by_laneop(<8 x i8> %a1, <8 x i8> %a2) { 104; CHECK-LABEL: test_vaddv_u8_used_by_laneop: 105; CHECK: addv.8b b[[REGNUM:[0-9]+]], v1 106; CHECK-NEXT: mov.b v0[3], v[[REGNUM]][0] 107; CHECK-NEXT: ret 108entry: 109 %0 = tail call i32 @llvm.aarch64.neon.uaddv.i32.v8i8(<8 x i8> %a2) 110 %1 = trunc i32 %0 to i8 111 %2 = insertelement <8 x i8> %a1, i8 %1, i32 3 112 ret <8 x i8> %2 113} 114 115define i32 @test_vaddv_u8_masked(<8 x i8> %a1) { 116; CHECK-LABEL: test_vaddv_u8_masked: 117; CHECK: addv.8b b[[REGNUM:[0-9]+]], v0 118; CHECK-NEXT: fmov w0, s[[REGNUM]] 119; CHECK-NEXT: ret 120entry: 121 %vaddv.i = tail call i32 @llvm.aarch64.neon.uaddv.i32.v8i8(<8 x i8> %a1) 122 %0 = and i32 %vaddv.i, 511 ; 0x1ff 123 ret i32 %0 124} 125 126define zeroext i16 @test_vaddv_u16(<4 x i16> %a1) { 127; CHECK-LABEL: test_vaddv_u16: 128; CHECK: addv.4h h[[REGNUM:[0-9]+]], v0 129; CHECK-NEXT: fmov w0, s[[REGNUM]] 130; CHECK-NEXT: ret 131entry: 132 %vaddv.i = tail call i32 @llvm.aarch64.neon.uaddv.i32.v4i16(<4 x i16> %a1) 133 %0 = trunc i32 %vaddv.i to i16 134 ret i16 %0 135} 136 137define <4 x i16> @test_vaddv_u16_used_by_laneop(<4 x i16> %a1, <4 x i16> %a2) { 138; CHECK-LABEL: test_vaddv_u16_used_by_laneop: 139; CHECK: addv.4h h[[REGNUM:[0-9]+]], v1 140; CHECK-NEXT: mov.h v0[3], v[[REGNUM]][0] 141; CHECK-NEXT: ret 142entry: 143 %0 = tail call i32 @llvm.aarch64.neon.uaddv.i32.v4i16(<4 x i16> %a2) 144 %1 = trunc i32 %0 to i16 145 %2 = insertelement <4 x i16> %a1, i16 %1, i32 3 146 ret <4 x i16> %2 147} 148 149define i32 @test_vaddv_u16_masked(<4 x i16> %a1) { 150; CHECK-LABEL: test_vaddv_u16_masked: 151; CHECK: addv.4h h[[REGNUM:[0-9]+]], v0 152; CHECK-NEXT: fmov w0, s[[REGNUM]] 153; CHECK-NEXT: ret 154entry: 155 %vaddv.i = tail call i32 @llvm.aarch64.neon.uaddv.i32.v4i16(<4 x i16> %a1) 156 %0 = and i32 %vaddv.i, 3276799 ; 0x31ffff 157 ret i32 %0 158} 159 160define i32 @test_vaddv_u32(<2 x i32> %a1) { 161; CHECK-LABEL: test_vaddv_u32: 162; 2 x i32 is not supported by the ISA, thus, this is a special case 163; CHECK: addp.2s v[[REGNUM:[0-9]+]], v0, v0 164; CHECK-NEXT: fmov w0, s[[REGNUM]] 165; CHECK-NEXT: ret 166entry: 167 %vaddv.i = tail call i32 @llvm.aarch64.neon.uaddv.i32.v2i32(<2 x i32> %a1) 168 ret i32 %vaddv.i 169} 170 171define <2 x i32> @test_vaddv_u32_used_by_laneop(<2 x i32> %a1, <2 x i32> %a2) { 172; CHECK-LABEL: test_vaddv_u32_used_by_laneop: 173; CHECK: addp.2s v[[REGNUM:[0-9]+]], v1, v1 174; CHECK-NEXT: mov.s v0[1], v[[REGNUM]][0] 175; CHECK-NEXT: ret 176entry: 177 %0 = tail call i32 @llvm.aarch64.neon.uaddv.i32.v2i32(<2 x i32> %a2) 178 %1 = insertelement <2 x i32> %a1, i32 %0, i32 1 179 ret <2 x i32> %1 180} 181 182define float @test_vaddv_f32(<2 x float> %a1) { 183; CHECK-LABEL: test_vaddv_f32: 184; CHECK: faddp.2s s0, v0 185; CHECK-NEXT: ret 186entry: 187 %vaddv.i = tail call float @llvm.aarch64.neon.faddv.f32.v2f32(<2 x float> %a1) 188 ret float %vaddv.i 189} 190 191define float @test_vaddv_v4f32(<4 x float> %a1) { 192; CHECK-LABEL: test_vaddv_v4f32: 193; CHECK: faddp.4s [[REGNUM:v[0-9]+]], v0, v0 194; CHECK: faddp.2s s0, [[REGNUM]] 195; CHECK-NEXT: ret 196entry: 197 %vaddv.i = tail call float @llvm.aarch64.neon.faddv.f32.v4f32(<4 x float> %a1) 198 ret float %vaddv.i 199} 200 201define double @test_vaddv_f64(<2 x double> %a1) { 202; CHECK-LABEL: test_vaddv_f64: 203; CHECK: faddp.2d d0, v0 204; CHECK-NEXT: ret 205entry: 206 %vaddv.i = tail call double @llvm.aarch64.neon.faddv.f64.v2f64(<2 x double> %a1) 207 ret double %vaddv.i 208} 209 210define i64 @test_vaddv_u64(<2 x i64> %a1) { 211; CHECK-LABEL: test_vaddv_u64: 212; CHECK: addp.2d [[REGNUM:d[0-9]+]], v0 213; CHECK-NEXT: fmov x0, [[REGNUM]] 214; CHECK-NEXT: ret 215entry: 216 %vaddv.i = tail call i64 @llvm.aarch64.neon.uaddv.i64.v2i64(<2 x i64> %a1) 217 ret i64 %vaddv.i 218} 219 220define <2 x i64> @test_vaddv_u64_used_by_laneop(<2 x i64> %a1, <2 x i64> %a2) { 221; CHECK-LABEL: test_vaddv_u64_used_by_laneop: 222; CHECK: addp.2d d[[REGNUM:[0-9]+]], v1 223; CHECK-NEXT: mov.d v0[1], v[[REGNUM]][0] 224; CHECK-NEXT: ret 225entry: 226 %0 = tail call i64 @llvm.aarch64.neon.uaddv.i64.v2i64(<2 x i64> %a2) 227 %1 = insertelement <2 x i64> %a1, i64 %0, i64 1 228 ret <2 x i64> %1 229} 230 231define <1 x i64> @test_vaddv_u64_to_vec(<2 x i64> %a1) { 232; CHECK-LABEL: test_vaddv_u64_to_vec: 233; CHECK: addp.2d d0, v0 234; CHECK-NOT: fmov 235; CHECK-NOT: ins 236; CHECK: ret 237entry: 238 %vaddv.i = tail call i64 @llvm.aarch64.neon.uaddv.i64.v2i64(<2 x i64> %a1) 239 %vec = insertelement <1 x i64> undef, i64 %vaddv.i, i32 0 240 ret <1 x i64> %vec 241} 242 243define signext i8 @test_vaddvq_s8(<16 x i8> %a1) { 244; CHECK-LABEL: test_vaddvq_s8: 245; CHECK: addv.16b b[[REGNUM:[0-9]+]], v0 246; CHECK-NEXT: smov.b w0, v[[REGNUM]][0] 247; CHECK-NEXT: ret 248entry: 249 %vaddv.i = tail call i32 @llvm.aarch64.neon.saddv.i32.v16i8(<16 x i8> %a1) 250 %0 = trunc i32 %vaddv.i to i8 251 ret i8 %0 252} 253 254define <16 x i8> @test_vaddvq_s8_used_by_laneop(<16 x i8> %a1, <16 x i8> %a2) { 255; CHECK-LABEL: test_vaddvq_s8_used_by_laneop: 256; CHECK: addv.16b b[[REGNUM:[0-9]+]], v1 257; CHECK-NEXT: mov.b v0[3], v[[REGNUM]][0] 258; CHECK-NEXT: ret 259entry: 260 %0 = tail call i32 @llvm.aarch64.neon.saddv.i32.v16i8(<16 x i8> %a2) 261 %1 = trunc i32 %0 to i8 262 %2 = insertelement <16 x i8> %a1, i8 %1, i32 3 263 ret <16 x i8> %2 264} 265 266define signext i16 @test_vaddvq_s16(<8 x i16> %a1) { 267; CHECK-LABEL: test_vaddvq_s16: 268; CHECK: addv.8h h[[REGNUM:[0-9]+]], v0 269; CHECK-NEXT: smov.h w0, v[[REGNUM]][0] 270; CHECK-NEXT: ret 271entry: 272 %vaddv.i = tail call i32 @llvm.aarch64.neon.saddv.i32.v8i16(<8 x i16> %a1) 273 %0 = trunc i32 %vaddv.i to i16 274 ret i16 %0 275} 276 277define <8 x i16> @test_vaddvq_s16_used_by_laneop(<8 x i16> %a1, <8 x i16> %a2) { 278; CHECK-LABEL: test_vaddvq_s16_used_by_laneop: 279; CHECK: addv.8h h[[REGNUM:[0-9]+]], v1 280; CHECK-NEXT: mov.h v0[3], v[[REGNUM]][0] 281; CHECK-NEXT: ret 282entry: 283 %0 = tail call i32 @llvm.aarch64.neon.saddv.i32.v8i16(<8 x i16> %a2) 284 %1 = trunc i32 %0 to i16 285 %2 = insertelement <8 x i16> %a1, i16 %1, i32 3 286 ret <8 x i16> %2 287} 288 289define i32 @test_vaddvq_s32(<4 x i32> %a1) { 290; CHECK-LABEL: test_vaddvq_s32: 291; CHECK: addv.4s [[REGNUM:s[0-9]+]], v0 292; CHECK-NEXT: fmov w0, [[REGNUM]] 293; CHECK-NEXT: ret 294entry: 295 %vaddv.i = tail call i32 @llvm.aarch64.neon.saddv.i32.v4i32(<4 x i32> %a1) 296 ret i32 %vaddv.i 297} 298 299define <4 x i32> @test_vaddvq_s32_used_by_laneop(<4 x i32> %a1, <4 x i32> %a2) { 300; CHECK-LABEL: test_vaddvq_s32_used_by_laneop: 301; CHECK: addv.4s s[[REGNUM:[0-9]+]], v1 302; CHECK-NEXT: mov.s v0[3], v[[REGNUM]][0] 303; CHECK-NEXT: ret 304entry: 305 %0 = tail call i32 @llvm.aarch64.neon.saddv.i32.v4i32(<4 x i32> %a2) 306 %1 = insertelement <4 x i32> %a1, i32 %0, i32 3 307 ret <4 x i32> %1 308} 309 310define zeroext i8 @test_vaddvq_u8(<16 x i8> %a1) { 311; CHECK-LABEL: test_vaddvq_u8: 312; CHECK: addv.16b b[[REGNUM:[0-9]+]], v0 313; CHECK-NEXT: fmov w0, s[[REGNUM]] 314; CHECK-NEXT: ret 315entry: 316 %vaddv.i = tail call i32 @llvm.aarch64.neon.uaddv.i32.v16i8(<16 x i8> %a1) 317 %0 = trunc i32 %vaddv.i to i8 318 ret i8 %0 319} 320 321define <16 x i8> @test_vaddvq_u8_used_by_laneop(<16 x i8> %a1, <16 x i8> %a2) { 322; CHECK-LABEL: test_vaddvq_u8_used_by_laneop: 323; CHECK: addv.16b b[[REGNUM:[0-9]+]], v1 324; CHECK-NEXT: mov.b v0[3], v[[REGNUM]][0] 325; CHECK-NEXT: ret 326entry: 327 %0 = tail call i32 @llvm.aarch64.neon.uaddv.i32.v16i8(<16 x i8> %a2) 328 %1 = trunc i32 %0 to i8 329 %2 = insertelement <16 x i8> %a1, i8 %1, i32 3 330 ret <16 x i8> %2 331} 332 333define zeroext i16 @test_vaddvq_u16(<8 x i16> %a1) { 334; CHECK-LABEL: test_vaddvq_u16: 335; CHECK: addv.8h h[[REGNUM:[0-9]+]], v0 336; CHECK-NEXT: fmov w0, s[[REGNUM]] 337; CHECK-NEXT: ret 338entry: 339 %vaddv.i = tail call i32 @llvm.aarch64.neon.uaddv.i32.v8i16(<8 x i16> %a1) 340 %0 = trunc i32 %vaddv.i to i16 341 ret i16 %0 342} 343 344define <8 x i16> @test_vaddvq_u16_used_by_laneop(<8 x i16> %a1, <8 x i16> %a2) { 345; CHECK-LABEL: test_vaddvq_u16_used_by_laneop: 346; CHECK: addv.8h h[[REGNUM:[0-9]+]], v1 347; CHECK-NEXT: mov.h v0[3], v[[REGNUM]][0] 348; CHECK-NEXT: ret 349entry: 350 %0 = tail call i32 @llvm.aarch64.neon.uaddv.i32.v8i16(<8 x i16> %a2) 351 %1 = trunc i32 %0 to i16 352 %2 = insertelement <8 x i16> %a1, i16 %1, i32 3 353 ret <8 x i16> %2 354} 355 356define i32 @test_vaddvq_u32(<4 x i32> %a1) { 357; CHECK-LABEL: test_vaddvq_u32: 358; CHECK: addv.4s [[REGNUM:s[0-9]+]], v0 359; CHECK-NEXT: fmov [[FMOVRES:w[0-9]+]], [[REGNUM]] 360; CHECK-NEXT: ret 361entry: 362 %vaddv.i = tail call i32 @llvm.aarch64.neon.uaddv.i32.v4i32(<4 x i32> %a1) 363 ret i32 %vaddv.i 364} 365 366define <4 x i32> @test_vaddvq_u32_used_by_laneop(<4 x i32> %a1, <4 x i32> %a2) { 367; CHECK-LABEL: test_vaddvq_u32_used_by_laneop: 368; CHECK: addv.4s s[[REGNUM:[0-9]+]], v1 369; CHECK-NEXT: mov.s v0[3], v[[REGNUM]][0] 370; CHECK-NEXT: ret 371entry: 372 %0 = tail call i32 @llvm.aarch64.neon.uaddv.i32.v4i32(<4 x i32> %a2) 373 %1 = insertelement <4 x i32> %a1, i32 %0, i32 3 374 ret <4 x i32> %1 375} 376 377declare i32 @llvm.aarch64.neon.uaddv.i32.v4i32(<4 x i32>) 378 379declare i32 @llvm.aarch64.neon.uaddv.i32.v8i16(<8 x i16>) 380 381declare i32 @llvm.aarch64.neon.uaddv.i32.v16i8(<16 x i8>) 382 383declare i32 @llvm.aarch64.neon.saddv.i32.v4i32(<4 x i32>) 384 385declare i32 @llvm.aarch64.neon.saddv.i32.v8i16(<8 x i16>) 386 387declare i32 @llvm.aarch64.neon.saddv.i32.v16i8(<16 x i8>) 388 389declare i64 @llvm.aarch64.neon.uaddv.i64.v2i64(<2 x i64>) 390 391declare i32 @llvm.aarch64.neon.uaddv.i32.v2i32(<2 x i32>) 392 393declare i32 @llvm.aarch64.neon.uaddv.i32.v4i16(<4 x i16>) 394 395declare i32 @llvm.aarch64.neon.uaddv.i32.v8i8(<8 x i8>) 396 397declare i32 @llvm.aarch64.neon.saddv.i32.v2i32(<2 x i32>) 398 399declare i64 @llvm.aarch64.neon.saddv.i64.v2i64(<2 x i64>) 400 401declare i32 @llvm.aarch64.neon.saddv.i32.v4i16(<4 x i16>) 402 403declare i32 @llvm.aarch64.neon.saddv.i32.v8i8(<8 x i8>) 404 405declare float @llvm.aarch64.neon.faddv.f32.v2f32(<2 x float> %a1) 406declare float @llvm.aarch64.neon.faddv.f32.v4f32(<4 x float> %a1) 407declare double @llvm.aarch64.neon.faddv.f64.v2f64(<2 x double> %a1) 408