[clang] [clang][clangir] add vpaddl and vpaddlq support (PR #191845)

Andrzej WarzyƄski via cfe-commits cfe-commits at lists.llvm.org
Thu Apr 16 04:11:52 PDT 2026


================
@@ -0,0 +1,155 @@
+// REQUIRES: aarch64-registered-target || arm-registered-target
+
+// RUN:                   %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -disable-O0-optnone -flax-vector-conversions=none           -emit-llvm -o - %s | opt -S -passes=mem2reg,sroa | FileCheck %s --check-prefixes=LLVM
+// RUN: %if cir-enabled %{%clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -disable-O0-optnone -flax-vector-conversions=none -fclangir -emit-llvm -o - %s | opt -S -passes=mem2reg,sroa | FileCheck %s --check-prefixes=LLVM %}
+// RUN: %if cir-enabled %{%clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -disable-O0-optnone -flax-vector-conversions=none -fclangir -emit-cir  -o - %s |                               FileCheck %s --check-prefixes=CIR %}
+
+#include <arm_neon.h>
+
+// LLVM-LABEL: @test_vpaddl_s8(
+// CIR-LABEL: @vpaddl_s8(
+int16x4_t test_vpaddl_s8(int8x8_t a) {
+// CIR:      cir.call_llvm_intrinsic "aarch64.neon.saddlp" %{{.*}} : (!cir.vector<8 x !s8i>) -> !cir.vector<4 x !s16i>
+
+// LLVM-SAME: <8 x i8> {{.*}} [[A:%.*]]) #[[ATTR0:[0-9]+]] {
+// LLVM:         [[VPADDL_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.saddlp.v4i16.v8i8(<8 x i8> [[A]])
+// LLVM-NEXT:    ret <4 x i16> [[VPADDL_I]]
+  return vpaddl_s8(a);
+}
+
+// LLVM-LABEL: @test_vpaddlq_s8(
+// CIR-LABEL: @vpaddlq_s8(
+int16x8_t test_vpaddlq_s8(int8x16_t a) {
+// CIR:      cir.call_llvm_intrinsic "aarch64.neon.saddlp" %{{.*}} : (!cir.vector<16 x !s8i>) -> !cir.vector<8 x !s16i>
+
+// LLVM-SAME: <16 x i8> {{.*}} [[A:%.*]]) #[[ATTR0]] {
+// LLVM:         [[VPADDL_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.saddlp.v8i16.v16i8(<16 x i8> [[A]])
+// LLVM-NEXT:    ret <8 x i16> [[VPADDL_I]]
+  return vpaddlq_s8(a);
+}
+
+// LLVM-LABEL: @test_vpaddl_s16(
+// CIR-LABEL: @vpaddl_s16(
+int32x2_t test_vpaddl_s16(int16x4_t a) {
+// CIR:      cir.call_llvm_intrinsic "aarch64.neon.saddlp" %{{.*}} : (!cir.vector<4 x !s16i>) -> !cir.vector<2 x !s32i>
+
+// LLVM-SAME: <4 x i16> {{.*}} [[A:%.*]]) #[[ATTR0]] {
+// LLVM:         [[TMP0:%.*]] = bitcast <4 x i16> [[A]] to <8 x i8>
+// LLVM-NEXT:    [[VPADDL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
+// LLVM-NEXT:    [[VPADDL1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.saddlp.v2i32.v4i16(<4 x i16> [[VPADDL_I]])
+// LLVM-NEXT:    ret <2 x i32> [[VPADDL1_I]]
+  return vpaddl_s16(a);
+}
+
+// LLVM-LABEL: @test_vpaddlq_s16(
+// CIR-LABEL: @vpaddlq_s16(
+int32x4_t test_vpaddlq_s16(int16x8_t a) {
+// CIR:      cir.call_llvm_intrinsic "aarch64.neon.saddlp" %{{.*}} : (!cir.vector<8 x !s16i>) -> !cir.vector<4 x !s32i>
+
+// LLVM-SAME: <8 x i16> {{.*}} [[A:%.*]]) #[[ATTR0]] {
+// LLVM:         [[TMP0:%.*]] = bitcast <8 x i16> [[A]] to <16 x i8>
+// LLVM-NEXT:    [[VPADDL_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
+// LLVM-NEXT:    [[VPADDL1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.saddlp.v4i32.v8i16(<8 x i16> [[VPADDL_I]])
+// LLVM-NEXT:    ret <4 x i32> [[VPADDL1_I]]
+  return vpaddlq_s16(a);
+}
+
+// LLVM-LABEL: @test_vpaddl_s32(
+// CIR-LABEL: @vpaddl_s32(
+int64x1_t test_vpaddl_s32(int32x2_t a) {
+// CIR:      cir.call_llvm_intrinsic "aarch64.neon.saddlp" %{{.*}} : (!cir.vector<2 x !s32i>) -> !cir.vector<1 x !s64i>
+
+// LLVM-SAME: <2 x i32> {{.*}} [[A:%.*]]) #[[ATTR0]] {
+// LLVM:         [[TMP0:%.*]] = bitcast <2 x i32> [[A]] to <8 x i8>
+// LLVM-NEXT:    [[VPADDL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
+// LLVM-NEXT:    [[VPADDL1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.saddlp.v1i64.v2i32(<2 x i32> [[VPADDL_I]])
+// LLVM-NEXT:    ret <1 x i64> [[VPADDL1_I]]
+  return vpaddl_s32(a);
+}
+
+// LLVM-LABEL: @test_vpaddlq_s32(
+// CIR-LABEL: @vpaddlq_s32(
+int64x2_t test_vpaddlq_s32(int32x4_t a) {
+// CIR:      cir.call_llvm_intrinsic "aarch64.neon.saddlp" %{{.*}} : (!cir.vector<4 x !s32i>) -> !cir.vector<2 x !s64i>
+
+// LLVM-SAME: <4 x i32> {{.*}} [[A:%.*]]) #[[ATTR0]] {
+// LLVM:         [[TMP0:%.*]] = bitcast <4 x i32> [[A]] to <16 x i8>
+// LLVM-NEXT:    [[VPADDL_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
+// LLVM-NEXT:    [[VPADDL1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.saddlp.v2i64.v4i32(<4 x i32> [[VPADDL_I]])
+// LLVM-NEXT:    ret <2 x i64> [[VPADDL1_I]]
+  return vpaddlq_s32(a);
+}
+
+// LLVM-LABEL: @test_vpaddl_u8(
+// CIR-LABEL: @vpaddl_u8(
+uint16x4_t test_vpaddl_u8(uint8x8_t a) {
+// CIR:      cir.call_llvm_intrinsic "aarch64.neon.uaddlp" %{{.*}} : (!cir.vector<8 x !u8i>) -> !cir.vector<4 x !u16i>
+
+// LLVM-SAME: <8 x i8> {{.*}} [[A:%.*]]) #[[ATTR0]] {
+// LLVM:         [[VPADDL_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uaddlp.v4i16.v8i8(<8 x i8> [[A]])
+// LLVM-NEXT:    ret <4 x i16> [[VPADDL_I]]
+  return vpaddl_u8(a);
+}
+
+// LLVM-LABEL: @test_vpaddlq_u8(
+// CIR-LABEL: @vpaddlq_u8(
+uint16x8_t test_vpaddlq_u8(uint8x16_t a) {
+// CIR:      cir.call_llvm_intrinsic "aarch64.neon.uaddlp" %{{.*}} : (!cir.vector<16 x !u8i>) -> !cir.vector<8 x !u16i>
+
+// LLVM-SAME: <16 x i8> {{.*}} [[A:%.*]]) #[[ATTR0]] {
+// LLVM:         [[VPADDL_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.uaddlp.v8i16.v16i8(<16 x i8> [[A]])
+// LLVM-NEXT:    ret <8 x i16> [[VPADDL_I]]
+  return vpaddlq_u8(a);
+}
+
+// LLVM-LABEL: @test_vpaddl_u16(
+// CIR-LABEL: @vpaddl_u16(
+uint32x2_t test_vpaddl_u16(uint16x4_t a) {
+// CIR:      cir.call_llvm_intrinsic "aarch64.neon.uaddlp" %{{.*}} : (!cir.vector<4 x !u16i>) -> !cir.vector<2 x !u32i>
+
+// LLVM-SAME: <4 x i16> {{.*}} [[A:%.*]]) #[[ATTR0]] {
+// LLVM:         [[TMP0:%.*]] = bitcast <4 x i16> [[A]] to <8 x i8>
+// LLVM-NEXT:    [[VPADDL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
+// LLVM-NEXT:    [[VPADDL1_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uaddlp.v2i32.v4i16(<4 x i16> [[VPADDL_I]])
+// LLVM-NEXT:    ret <2 x i32> [[VPADDL1_I]]
+  return vpaddl_u16(a);
+}
+
+// LLVM-LABEL: @test_vpaddlq_u16(
+// CIR-LABEL: @vpaddlq_u16(
+uint32x4_t test_vpaddlq_u16(uint16x8_t a) {
+// CIR:      cir.call_llvm_intrinsic "aarch64.neon.uaddlp" %{{.*}} : (!cir.vector<8 x !u16i>) -> !cir.vector<4 x !u32i>
+
+// LLVM-SAME: <8 x i16> {{.*}} [[A:%.*]]) #[[ATTR0]] {
+// LLVM:         [[TMP0:%.*]] = bitcast <8 x i16> [[A]] to <16 x i8>
+// LLVM-NEXT:    [[VPADDL_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16>
+// LLVM-NEXT:    [[VPADDL1_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.uaddlp.v4i32.v8i16(<8 x i16> [[VPADDL_I]])
+// LLVM-NEXT:    ret <4 x i32> [[VPADDL1_I]]
+  return vpaddlq_u16(a);
+}
+
+// LLVM-LABEL: @test_vpaddl_u32(
+// CIR-LABEL: @vpaddl_u32(
+uint64x1_t test_vpaddl_u32(uint32x2_t a) {
+// CIR:      cir.call_llvm_intrinsic "aarch64.neon.uaddlp" %{{.*}} : (!cir.vector<2 x !u32i>) -> !cir.vector<1 x !u64i>
+
+// LLVM-SAME: <2 x i32> {{.*}} [[A:%.*]]) #[[ATTR0]] {
+// LLVM:         [[TMP0:%.*]] = bitcast <2 x i32> [[A]] to <8 x i8>
+// LLVM-NEXT:    [[VPADDL_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
+// LLVM-NEXT:    [[VPADDL1_I:%.*]] = call <1 x i64> @llvm.aarch64.neon.uaddlp.v1i64.v2i32(<2 x i32> [[VPADDL_I]])
+// LLVM-NEXT:    ret <1 x i64> [[VPADDL1_I]]
+  return vpaddl_u32(a);
+}
+
+// LLVM-LABEL: @test_vpaddlq_u32(
+// CIR-LABEL: @vpaddlq_u32(
+uint64x2_t test_vpaddlq_u32(uint32x4_t a) {
+// CIR:      cir.call_llvm_intrinsic "aarch64.neon.uaddlp" %{{.*}} : (!cir.vector<4 x !u32i>) -> !cir.vector<2 x !u64i>
+
+// LLVM-SAME: <4 x i32> {{.*}} [[A:%.*]]) #[[ATTR0]] {
+// LLVM:         [[TMP0:%.*]] = bitcast <4 x i32> [[A]] to <16 x i8>
+// LLVM-NEXT:    [[VPADDL_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32>
+// LLVM-NEXT:    [[VPADDL1_I:%.*]] = call <2 x i64> @llvm.aarch64.neon.uaddlp.v2i64.v4i32(<4 x i32> [[VPADDL_I]])
+// LLVM-NEXT:    ret <2 x i64> [[VPADDL1_I]]
+  return vpaddlq_u32(a);
+}
----------------
banach-space wrote:

Missing EOF

https://github.com/llvm/llvm-project/pull/191845


More information about the cfe-commits mailing list