https://github.com/iamvickynguyen updated https://github.com/llvm/llvm-project/pull/204989
>From 0825a8a021c922ad88ce7e43695967d5ee112a92 Mon Sep 17 00:00:00 2001 From: Vicky Nguyen <[email protected]> Date: Fri, 19 Jun 2026 09:50:15 -0700 Subject: [PATCH 1/2] [CIR][AArch63] Upstream narrowing-addition NEON builtins --- .../lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp | 43 +- clang/test/CodeGen/AArch64/neon-intrinsics.c | 724 ------------------ clang/test/CodeGen/AArch64/neon/add.c | 596 ++++++++++++++ 3 files changed, 638 insertions(+), 725 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp index 8b077620d2bab..c5c7cba910ea3 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp @@ -685,7 +685,30 @@ static mlir::Value emitCommonNeonBuiltinExpr( mlir::Value result = cgf.getBuilder().createXor(loc, ops[0], ops[1]); return cgf.getBuilder().createBitcast(result, ty); } - case NEON::BI__builtin_neon_vaddhn_v: + case NEON::BI__builtin_neon_vaddhn_v: { + // srcTy has double-width elements (e.g. <8 x i16> when VTy is <8 x i8>). + // Unsigned so createShiftRight emits lshr, not ashr. + cir::VectorType srcTy = + cgf.getBuilder().getExtendedOrTruncatedElementVectorType( + vTy, /*isExtended=*/true, /*isSigned=*/false); + + // %sum = add <4 x i32> %lhs, %rhs + ops[0] = cgf.getBuilder().createBitcast(ops[0], srcTy); + ops[1] = cgf.getBuilder().createBitcast(ops[1], srcTy); + mlir::Value result = cgf.getBuilder().createAdd(loc, ops[0], ops[1]); + + // %high = lshr <4 x i32> %sum, <i32 16, i32 16, i32 16, i32 16> + auto wideEltTy = mlir::cast<cir::IntType>(srcTy.getElementType()); + mlir::Value shiftAmt = cgf.getBuilder().getConstantInt( + loc, wideEltTy, wideEltTy.getWidth() / 2); + mlir::Value shiftVec = + emitNeonShiftVector(cgf.getBuilder(), shiftAmt, srcTy, loc, + /*neg=*/false); + result = cgf.getBuilder().createShiftRight(loc, result, shiftVec); + + // %res = trunc <4 x i32> %high to <4 x i16> + return cgf.getBuilder().createIntCast(result, vTy); + } case NEON::BI__builtin_neon_vcale_v: case NEON::BI__builtin_neon_vcaleq_v: case NEON::BI__builtin_neon_vcalt_v: @@ -1060,6 +1083,10 @@ static mlir::Value emitCommonNeonBuiltinExpr( std::string("unimplemented AArch64 builtin call: ") + cgf.getContext().BuiltinInfo.getName(builtinID)); break; + case NEON::BI__builtin_neon_vhadd_v: + case NEON::BI__builtin_neon_vhaddq_v: + case NEON::BI__builtin_neon_vrhadd_v: + case NEON::BI__builtin_neon_vrhaddq_v: case NEON::BI__builtin_neon_vshl_v: case NEON::BI__builtin_neon_vshlq_v: { llvm::StringRef llvmIntrName = @@ -1073,6 +1100,20 @@ static mlir::Value emitCommonNeonBuiltinExpr( mlir::Type resultType = cgf.convertType(expr->getType()); return cgf.getBuilder().createBitcast(result, resultType); } + case NEON::BI__builtin_neon_vraddhn_v: { + cir::VectorType srcTy = + cgf.getBuilder().getExtendedOrTruncatedElementVectorType( + vTy, /*isExtended=*/true); + + llvm::StringRef llvmIntrName = getLLVMIntrNameNoPrefix( + static_cast<llvm::Intrinsic::ID>(llvmIntrinsic)); + mlir::Value result = + emitNeonCall(cgf.getCIRGenModule(), cgf.getBuilder(), + /*argTypes=*/{srcTy, srcTy}, ops, llvmIntrName, + /*funcResTy=*/vTy, loc); + mlir::Type resultType = cgf.convertType(expr->getType()); + return cgf.getBuilder().createBitcast(result, resultType); + } } // NYI diff --git a/clang/test/CodeGen/AArch64/neon-intrinsics.c b/clang/test/CodeGen/AArch64/neon-intrinsics.c index b37ed5aa29f10..78b4495e9f8cc 100644 --- a/clang/test/CodeGen/AArch64/neon-intrinsics.c +++ b/clang/test/CodeGen/AArch64/neon-intrinsics.c @@ -2404,174 +2404,6 @@ uint64x2_t test_vcltq_f64(float64x2_t v1, float64x2_t v2) { return vcltq_f64(v1, v2); } -// CHECK-LABEL: define dso_local <8 x i8> @test_vhadd_s8( -// CHECK-SAME: <8 x i8> noundef [[V1:%.*]], <8 x i8> noundef [[V2:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[VHADD_V_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.shadd.v8i8(<8 x i8> [[V1]], <8 x i8> [[V2]]) -// CHECK-NEXT: ret <8 x i8> [[VHADD_V_I]] -// -int8x8_t test_vhadd_s8(int8x8_t v1, int8x8_t v2) { - return vhadd_s8(v1, v2); -} - -// CHECK-LABEL: define dso_local <4 x i16> @test_vhadd_s16( -// CHECK-SAME: <4 x i16> noundef [[V1:%.*]], <4 x i16> noundef [[V2:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i16> [[V1]] to <8 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i16> [[V2]] to <8 x i8> -// CHECK-NEXT: [[VHADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16> -// CHECK-NEXT: [[VHADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16> -// CHECK-NEXT: [[VHADD_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.shadd.v4i16(<4 x i16> [[VHADD_V_I]], <4 x i16> [[VHADD_V1_I]]) -// CHECK-NEXT: [[VHADD_V3_I:%.*]] = bitcast <4 x i16> [[VHADD_V2_I]] to <8 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[VHADD_V3_I]] to <4 x i16> -// CHECK-NEXT: ret <4 x i16> [[TMP2]] -// -int16x4_t test_vhadd_s16(int16x4_t v1, int16x4_t v2) { - return vhadd_s16(v1, v2); -} - -// CHECK-LABEL: define dso_local <2 x i32> @test_vhadd_s32( -// CHECK-SAME: <2 x i32> noundef [[V1:%.*]], <2 x i32> noundef [[V2:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[V1]] to <8 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x i32> [[V2]] to <8 x i8> -// CHECK-NEXT: [[VHADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32> -// CHECK-NEXT: [[VHADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32> -// CHECK-NEXT: [[VHADD_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.shadd.v2i32(<2 x i32> [[VHADD_V_I]], <2 x i32> [[VHADD_V1_I]]) -// CHECK-NEXT: [[VHADD_V3_I:%.*]] = bitcast <2 x i32> [[VHADD_V2_I]] to <8 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[VHADD_V3_I]] to <2 x i32> -// CHECK-NEXT: ret <2 x i32> [[TMP2]] -// -int32x2_t test_vhadd_s32(int32x2_t v1, int32x2_t v2) { - return vhadd_s32(v1, v2); -} - -// CHECK-LABEL: define dso_local <8 x i8> @test_vhadd_u8( -// CHECK-SAME: <8 x i8> noundef [[V1:%.*]], <8 x i8> noundef [[V2:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[VHADD_V_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.uhadd.v8i8(<8 x i8> [[V1]], <8 x i8> [[V2]]) -// CHECK-NEXT: ret <8 x i8> [[VHADD_V_I]] -// -uint8x8_t test_vhadd_u8(uint8x8_t v1, uint8x8_t v2) { - return vhadd_u8(v1, v2); -} - -// CHECK-LABEL: define dso_local <4 x i16> @test_vhadd_u16( -// CHECK-SAME: <4 x i16> noundef [[V1:%.*]], <4 x i16> noundef [[V2:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i16> [[V1]] to <8 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i16> [[V2]] to <8 x i8> -// CHECK-NEXT: [[VHADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16> -// CHECK-NEXT: [[VHADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16> -// CHECK-NEXT: [[VHADD_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.uhadd.v4i16(<4 x i16> [[VHADD_V_I]], <4 x i16> [[VHADD_V1_I]]) -// CHECK-NEXT: [[VHADD_V3_I:%.*]] = bitcast <4 x i16> [[VHADD_V2_I]] to <8 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[VHADD_V3_I]] to <4 x i16> -// CHECK-NEXT: ret <4 x i16> [[TMP2]] -// -uint16x4_t test_vhadd_u16(uint16x4_t v1, uint16x4_t v2) { - return vhadd_u16(v1, v2); -} - -// CHECK-LABEL: define dso_local <2 x i32> @test_vhadd_u32( -// CHECK-SAME: <2 x i32> noundef [[V1:%.*]], <2 x i32> noundef [[V2:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[V1]] to <8 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x i32> [[V2]] to <8 x i8> -// CHECK-NEXT: [[VHADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32> -// CHECK-NEXT: [[VHADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32> -// CHECK-NEXT: [[VHADD_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.uhadd.v2i32(<2 x i32> [[VHADD_V_I]], <2 x i32> [[VHADD_V1_I]]) -// CHECK-NEXT: [[VHADD_V3_I:%.*]] = bitcast <2 x i32> [[VHADD_V2_I]] to <8 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[VHADD_V3_I]] to <2 x i32> -// CHECK-NEXT: ret <2 x i32> [[TMP2]] -// -uint32x2_t test_vhadd_u32(uint32x2_t v1, uint32x2_t v2) { - return vhadd_u32(v1, v2); -} - -// CHECK-LABEL: define dso_local <16 x i8> @test_vhaddq_s8( -// CHECK-SAME: <16 x i8> noundef [[V1:%.*]], <16 x i8> noundef [[V2:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[VHADDQ_V_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.shadd.v16i8(<16 x i8> [[V1]], <16 x i8> [[V2]]) -// CHECK-NEXT: ret <16 x i8> [[VHADDQ_V_I]] -// -int8x16_t test_vhaddq_s8(int8x16_t v1, int8x16_t v2) { - return vhaddq_s8(v1, v2); -} - -// CHECK-LABEL: define dso_local <8 x i16> @test_vhaddq_s16( -// CHECK-SAME: <8 x i16> noundef [[V1:%.*]], <8 x i16> noundef [[V2:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <8 x i16> [[V1]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i16> [[V2]] to <16 x i8> -// CHECK-NEXT: [[VHADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16> -// CHECK-NEXT: [[VHADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16> -// CHECK-NEXT: [[VHADDQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.shadd.v8i16(<8 x i16> [[VHADDQ_V_I]], <8 x i16> [[VHADDQ_V1_I]]) -// CHECK-NEXT: [[VHADDQ_V3_I:%.*]] = bitcast <8 x i16> [[VHADDQ_V2_I]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[VHADDQ_V3_I]] to <8 x i16> -// CHECK-NEXT: ret <8 x i16> [[TMP2]] -// -int16x8_t test_vhaddq_s16(int16x8_t v1, int16x8_t v2) { - return vhaddq_s16(v1, v2); -} - -// CHECK-LABEL: define dso_local <4 x i32> @test_vhaddq_s32( -// CHECK-SAME: <4 x i32> noundef [[V1:%.*]], <4 x i32> noundef [[V2:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[V1]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[V2]] to <16 x i8> -// CHECK-NEXT: [[VHADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32> -// CHECK-NEXT: [[VHADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32> -// CHECK-NEXT: [[VHADDQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.shadd.v4i32(<4 x i32> [[VHADDQ_V_I]], <4 x i32> [[VHADDQ_V1_I]]) -// CHECK-NEXT: [[VHADDQ_V3_I:%.*]] = bitcast <4 x i32> [[VHADDQ_V2_I]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[VHADDQ_V3_I]] to <4 x i32> -// CHECK-NEXT: ret <4 x i32> [[TMP2]] -// -int32x4_t test_vhaddq_s32(int32x4_t v1, int32x4_t v2) { - return vhaddq_s32(v1, v2); -} - -// CHECK-LABEL: define dso_local <16 x i8> @test_vhaddq_u8( -// CHECK-SAME: <16 x i8> noundef [[V1:%.*]], <16 x i8> noundef [[V2:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[VHADDQ_V_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.uhadd.v16i8(<16 x i8> [[V1]], <16 x i8> [[V2]]) -// CHECK-NEXT: ret <16 x i8> [[VHADDQ_V_I]] -// -uint8x16_t test_vhaddq_u8(uint8x16_t v1, uint8x16_t v2) { - return vhaddq_u8(v1, v2); -} - -// CHECK-LABEL: define dso_local <8 x i16> @test_vhaddq_u16( -// CHECK-SAME: <8 x i16> noundef [[V1:%.*]], <8 x i16> noundef [[V2:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <8 x i16> [[V1]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i16> [[V2]] to <16 x i8> -// CHECK-NEXT: [[VHADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16> -// CHECK-NEXT: [[VHADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16> -// CHECK-NEXT: [[VHADDQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.uhadd.v8i16(<8 x i16> [[VHADDQ_V_I]], <8 x i16> [[VHADDQ_V1_I]]) -// CHECK-NEXT: [[VHADDQ_V3_I:%.*]] = bitcast <8 x i16> [[VHADDQ_V2_I]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[VHADDQ_V3_I]] to <8 x i16> -// CHECK-NEXT: ret <8 x i16> [[TMP2]] -// -uint16x8_t test_vhaddq_u16(uint16x8_t v1, uint16x8_t v2) { - return vhaddq_u16(v1, v2); -} - -// CHECK-LABEL: define dso_local <4 x i32> @test_vhaddq_u32( -// CHECK-SAME: <4 x i32> noundef [[V1:%.*]], <4 x i32> noundef [[V2:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[V1]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[V2]] to <16 x i8> -// CHECK-NEXT: [[VHADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32> -// CHECK-NEXT: [[VHADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32> -// CHECK-NEXT: [[VHADDQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.uhadd.v4i32(<4 x i32> [[VHADDQ_V_I]], <4 x i32> [[VHADDQ_V1_I]]) -// CHECK-NEXT: [[VHADDQ_V3_I:%.*]] = bitcast <4 x i32> [[VHADDQ_V2_I]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[VHADDQ_V3_I]] to <4 x i32> -// CHECK-NEXT: ret <4 x i32> [[TMP2]] -// -uint32x4_t test_vhaddq_u32(uint32x4_t v1, uint32x4_t v2) { - return vhaddq_u32(v1, v2); -} - // CHECK-LABEL: define dso_local <8 x i8> @test_vhsub_s8( // CHECK-SAME: <8 x i8> noundef [[V1:%.*]], <8 x i8> noundef [[V2:%.*]]) #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] @@ -2740,174 +2572,6 @@ uint32x4_t test_vhsubq_u32(uint32x4_t v1, uint32x4_t v2) { return vhsubq_u32(v1, v2); } -// CHECK-LABEL: define dso_local <8 x i8> @test_vrhadd_s8( -// CHECK-SAME: <8 x i8> noundef [[V1:%.*]], <8 x i8> noundef [[V2:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[VRHADD_V_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.srhadd.v8i8(<8 x i8> [[V1]], <8 x i8> [[V2]]) -// CHECK-NEXT: ret <8 x i8> [[VRHADD_V_I]] -// -int8x8_t test_vrhadd_s8(int8x8_t v1, int8x8_t v2) { - return vrhadd_s8(v1, v2); -} - -// CHECK-LABEL: define dso_local <4 x i16> @test_vrhadd_s16( -// CHECK-SAME: <4 x i16> noundef [[V1:%.*]], <4 x i16> noundef [[V2:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i16> [[V1]] to <8 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i16> [[V2]] to <8 x i8> -// CHECK-NEXT: [[VRHADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16> -// CHECK-NEXT: [[VRHADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16> -// CHECK-NEXT: [[VRHADD_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.srhadd.v4i16(<4 x i16> [[VRHADD_V_I]], <4 x i16> [[VRHADD_V1_I]]) -// CHECK-NEXT: [[VRHADD_V3_I:%.*]] = bitcast <4 x i16> [[VRHADD_V2_I]] to <8 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[VRHADD_V3_I]] to <4 x i16> -// CHECK-NEXT: ret <4 x i16> [[TMP2]] -// -int16x4_t test_vrhadd_s16(int16x4_t v1, int16x4_t v2) { - return vrhadd_s16(v1, v2); -} - -// CHECK-LABEL: define dso_local <2 x i32> @test_vrhadd_s32( -// CHECK-SAME: <2 x i32> noundef [[V1:%.*]], <2 x i32> noundef [[V2:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[V1]] to <8 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x i32> [[V2]] to <8 x i8> -// CHECK-NEXT: [[VRHADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32> -// CHECK-NEXT: [[VRHADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32> -// CHECK-NEXT: [[VRHADD_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.srhadd.v2i32(<2 x i32> [[VRHADD_V_I]], <2 x i32> [[VRHADD_V1_I]]) -// CHECK-NEXT: [[VRHADD_V3_I:%.*]] = bitcast <2 x i32> [[VRHADD_V2_I]] to <8 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[VRHADD_V3_I]] to <2 x i32> -// CHECK-NEXT: ret <2 x i32> [[TMP2]] -// -int32x2_t test_vrhadd_s32(int32x2_t v1, int32x2_t v2) { - return vrhadd_s32(v1, v2); -} - -// CHECK-LABEL: define dso_local <8 x i8> @test_vrhadd_u8( -// CHECK-SAME: <8 x i8> noundef [[V1:%.*]], <8 x i8> noundef [[V2:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[VRHADD_V_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.urhadd.v8i8(<8 x i8> [[V1]], <8 x i8> [[V2]]) -// CHECK-NEXT: ret <8 x i8> [[VRHADD_V_I]] -// -uint8x8_t test_vrhadd_u8(uint8x8_t v1, uint8x8_t v2) { - return vrhadd_u8(v1, v2); -} - -// CHECK-LABEL: define dso_local <4 x i16> @test_vrhadd_u16( -// CHECK-SAME: <4 x i16> noundef [[V1:%.*]], <4 x i16> noundef [[V2:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i16> [[V1]] to <8 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i16> [[V2]] to <8 x i8> -// CHECK-NEXT: [[VRHADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16> -// CHECK-NEXT: [[VRHADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16> -// CHECK-NEXT: [[VRHADD_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.urhadd.v4i16(<4 x i16> [[VRHADD_V_I]], <4 x i16> [[VRHADD_V1_I]]) -// CHECK-NEXT: [[VRHADD_V3_I:%.*]] = bitcast <4 x i16> [[VRHADD_V2_I]] to <8 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[VRHADD_V3_I]] to <4 x i16> -// CHECK-NEXT: ret <4 x i16> [[TMP2]] -// -uint16x4_t test_vrhadd_u16(uint16x4_t v1, uint16x4_t v2) { - return vrhadd_u16(v1, v2); -} - -// CHECK-LABEL: define dso_local <2 x i32> @test_vrhadd_u32( -// CHECK-SAME: <2 x i32> noundef [[V1:%.*]], <2 x i32> noundef [[V2:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x i32> [[V1]] to <8 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x i32> [[V2]] to <8 x i8> -// CHECK-NEXT: [[VRHADD_V_I:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32> -// CHECK-NEXT: [[VRHADD_V1_I:%.*]] = bitcast <8 x i8> [[TMP1]] to <2 x i32> -// CHECK-NEXT: [[VRHADD_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.urhadd.v2i32(<2 x i32> [[VRHADD_V_I]], <2 x i32> [[VRHADD_V1_I]]) -// CHECK-NEXT: [[VRHADD_V3_I:%.*]] = bitcast <2 x i32> [[VRHADD_V2_I]] to <8 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[VRHADD_V3_I]] to <2 x i32> -// CHECK-NEXT: ret <2 x i32> [[TMP2]] -// -uint32x2_t test_vrhadd_u32(uint32x2_t v1, uint32x2_t v2) { - return vrhadd_u32(v1, v2); -} - -// CHECK-LABEL: define dso_local <16 x i8> @test_vrhaddq_s8( -// CHECK-SAME: <16 x i8> noundef [[V1:%.*]], <16 x i8> noundef [[V2:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[VRHADDQ_V_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.srhadd.v16i8(<16 x i8> [[V1]], <16 x i8> [[V2]]) -// CHECK-NEXT: ret <16 x i8> [[VRHADDQ_V_I]] -// -int8x16_t test_vrhaddq_s8(int8x16_t v1, int8x16_t v2) { - return vrhaddq_s8(v1, v2); -} - -// CHECK-LABEL: define dso_local <8 x i16> @test_vrhaddq_s16( -// CHECK-SAME: <8 x i16> noundef [[V1:%.*]], <8 x i16> noundef [[V2:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <8 x i16> [[V1]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i16> [[V2]] to <16 x i8> -// CHECK-NEXT: [[VRHADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16> -// CHECK-NEXT: [[VRHADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16> -// CHECK-NEXT: [[VRHADDQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.srhadd.v8i16(<8 x i16> [[VRHADDQ_V_I]], <8 x i16> [[VRHADDQ_V1_I]]) -// CHECK-NEXT: [[VRHADDQ_V3_I:%.*]] = bitcast <8 x i16> [[VRHADDQ_V2_I]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[VRHADDQ_V3_I]] to <8 x i16> -// CHECK-NEXT: ret <8 x i16> [[TMP2]] -// -int16x8_t test_vrhaddq_s16(int16x8_t v1, int16x8_t v2) { - return vrhaddq_s16(v1, v2); -} - -// CHECK-LABEL: define dso_local <4 x i32> @test_vrhaddq_s32( -// CHECK-SAME: <4 x i32> noundef [[V1:%.*]], <4 x i32> noundef [[V2:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[V1]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[V2]] to <16 x i8> -// CHECK-NEXT: [[VRHADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32> -// CHECK-NEXT: [[VRHADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32> -// CHECK-NEXT: [[VRHADDQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.srhadd.v4i32(<4 x i32> [[VRHADDQ_V_I]], <4 x i32> [[VRHADDQ_V1_I]]) -// CHECK-NEXT: [[VRHADDQ_V3_I:%.*]] = bitcast <4 x i32> [[VRHADDQ_V2_I]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[VRHADDQ_V3_I]] to <4 x i32> -// CHECK-NEXT: ret <4 x i32> [[TMP2]] -// -int32x4_t test_vrhaddq_s32(int32x4_t v1, int32x4_t v2) { - return vrhaddq_s32(v1, v2); -} - -// CHECK-LABEL: define dso_local <16 x i8> @test_vrhaddq_u8( -// CHECK-SAME: <16 x i8> noundef [[V1:%.*]], <16 x i8> noundef [[V2:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[VRHADDQ_V_I:%.*]] = call <16 x i8> @llvm.aarch64.neon.urhadd.v16i8(<16 x i8> [[V1]], <16 x i8> [[V2]]) -// CHECK-NEXT: ret <16 x i8> [[VRHADDQ_V_I]] -// -uint8x16_t test_vrhaddq_u8(uint8x16_t v1, uint8x16_t v2) { - return vrhaddq_u8(v1, v2); -} - -// CHECK-LABEL: define dso_local <8 x i16> @test_vrhaddq_u16( -// CHECK-SAME: <8 x i16> noundef [[V1:%.*]], <8 x i16> noundef [[V2:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <8 x i16> [[V1]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i16> [[V2]] to <16 x i8> -// CHECK-NEXT: [[VRHADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16> -// CHECK-NEXT: [[VRHADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16> -// CHECK-NEXT: [[VRHADDQ_V2_I:%.*]] = call <8 x i16> @llvm.aarch64.neon.urhadd.v8i16(<8 x i16> [[VRHADDQ_V_I]], <8 x i16> [[VRHADDQ_V1_I]]) -// CHECK-NEXT: [[VRHADDQ_V3_I:%.*]] = bitcast <8 x i16> [[VRHADDQ_V2_I]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[VRHADDQ_V3_I]] to <8 x i16> -// CHECK-NEXT: ret <8 x i16> [[TMP2]] -// -uint16x8_t test_vrhaddq_u16(uint16x8_t v1, uint16x8_t v2) { - return vrhaddq_u16(v1, v2); -} - -// CHECK-LABEL: define dso_local <4 x i32> @test_vrhaddq_u32( -// CHECK-SAME: <4 x i32> noundef [[V1:%.*]], <4 x i32> noundef [[V2:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[V1]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[V2]] to <16 x i8> -// CHECK-NEXT: [[VRHADDQ_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32> -// CHECK-NEXT: [[VRHADDQ_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32> -// CHECK-NEXT: [[VRHADDQ_V2_I:%.*]] = call <4 x i32> @llvm.aarch64.neon.urhadd.v4i32(<4 x i32> [[VRHADDQ_V_I]], <4 x i32> [[VRHADDQ_V1_I]]) -// CHECK-NEXT: [[VRHADDQ_V3_I:%.*]] = bitcast <4 x i32> [[VRHADDQ_V2_I]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[VRHADDQ_V3_I]] to <4 x i32> -// CHECK-NEXT: ret <4 x i32> [[TMP2]] -// -uint32x4_t test_vrhaddq_u32(uint32x4_t v1, uint32x4_t v2) { - return vrhaddq_u32(v1, v2); -} - // CHECK-LABEL: define dso_local <8 x i8> @test_vqadd_s8( // CHECK-SAME: <8 x i8> noundef [[A:%.*]], <8 x i8> noundef [[B:%.*]]) #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] @@ -5399,394 +5063,6 @@ uint64x2_t test_vsubw_high_u32(uint64x2_t a, uint32x4_t b) { return vsubw_high_u32(a, b); } -// CHECK-LABEL: define dso_local <8 x i8> @test_vaddhn_s16( -// CHECK-SAME: <8 x i16> noundef [[A:%.*]], <8 x i16> noundef [[B:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <8 x i16> [[A]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i16> [[B]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16> -// CHECK-NEXT: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16> -// CHECK-NEXT: [[VADDHN_I:%.*]] = add <8 x i16> [[TMP2]], [[TMP3]] -// CHECK-NEXT: [[VADDHN1_I:%.*]] = lshr <8 x i16> [[VADDHN_I]], splat (i16 8) -// CHECK-NEXT: [[VADDHN2_I:%.*]] = trunc <8 x i16> [[VADDHN1_I]] to <8 x i8> -// CHECK-NEXT: ret <8 x i8> [[VADDHN2_I]] -// -int8x8_t test_vaddhn_s16(int16x8_t a, int16x8_t b) { - return vaddhn_s16(a, b); -} - -// CHECK-LABEL: define dso_local <4 x i16> @test_vaddhn_s32( -// CHECK-SAME: <4 x i32> noundef [[A:%.*]], <4 x i32> noundef [[B:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32> -// CHECK-NEXT: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32> -// CHECK-NEXT: [[VADDHN_I:%.*]] = add <4 x i32> [[TMP2]], [[TMP3]] -// CHECK-NEXT: [[VADDHN1_I:%.*]] = lshr <4 x i32> [[VADDHN_I]], splat (i32 16) -// CHECK-NEXT: [[VADDHN2_I:%.*]] = trunc <4 x i32> [[VADDHN1_I]] to <4 x i16> -// CHECK-NEXT: ret <4 x i16> [[VADDHN2_I]] -// -int16x4_t test_vaddhn_s32(int32x4_t a, int32x4_t b) { - return vaddhn_s32(a, b); -} - -// CHECK-LABEL: define dso_local <2 x i32> @test_vaddhn_s64( -// CHECK-SAME: <2 x i64> noundef [[A:%.*]], <2 x i64> noundef [[B:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x i64> [[A]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x i64> [[B]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64> -// CHECK-NEXT: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64> -// CHECK-NEXT: [[VADDHN_I:%.*]] = add <2 x i64> [[TMP2]], [[TMP3]] -// CHECK-NEXT: [[VADDHN1_I:%.*]] = lshr <2 x i64> [[VADDHN_I]], splat (i64 32) -// CHECK-NEXT: [[VADDHN2_I:%.*]] = trunc <2 x i64> [[VADDHN1_I]] to <2 x i32> -// CHECK-NEXT: ret <2 x i32> [[VADDHN2_I]] -// -int32x2_t test_vaddhn_s64(int64x2_t a, int64x2_t b) { - return vaddhn_s64(a, b); -} - -// CHECK-LABEL: define dso_local <8 x i8> @test_vaddhn_u16( -// CHECK-SAME: <8 x i16> noundef [[A:%.*]], <8 x i16> noundef [[B:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <8 x i16> [[A]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i16> [[B]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16> -// CHECK-NEXT: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16> -// CHECK-NEXT: [[VADDHN_I:%.*]] = add <8 x i16> [[TMP2]], [[TMP3]] -// CHECK-NEXT: [[VADDHN1_I:%.*]] = lshr <8 x i16> [[VADDHN_I]], splat (i16 8) -// CHECK-NEXT: [[VADDHN2_I:%.*]] = trunc <8 x i16> [[VADDHN1_I]] to <8 x i8> -// CHECK-NEXT: ret <8 x i8> [[VADDHN2_I]] -// -uint8x8_t test_vaddhn_u16(uint16x8_t a, uint16x8_t b) { - return vaddhn_u16(a, b); -} - -// CHECK-LABEL: define dso_local <4 x i16> @test_vaddhn_u32( -// CHECK-SAME: <4 x i32> noundef [[A:%.*]], <4 x i32> noundef [[B:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32> -// CHECK-NEXT: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32> -// CHECK-NEXT: [[VADDHN_I:%.*]] = add <4 x i32> [[TMP2]], [[TMP3]] -// CHECK-NEXT: [[VADDHN1_I:%.*]] = lshr <4 x i32> [[VADDHN_I]], splat (i32 16) -// CHECK-NEXT: [[VADDHN2_I:%.*]] = trunc <4 x i32> [[VADDHN1_I]] to <4 x i16> -// CHECK-NEXT: ret <4 x i16> [[VADDHN2_I]] -// -uint16x4_t test_vaddhn_u32(uint32x4_t a, uint32x4_t b) { - return vaddhn_u32(a, b); -} - -// CHECK-LABEL: define dso_local <2 x i32> @test_vaddhn_u64( -// CHECK-SAME: <2 x i64> noundef [[A:%.*]], <2 x i64> noundef [[B:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x i64> [[A]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x i64> [[B]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64> -// CHECK-NEXT: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64> -// CHECK-NEXT: [[VADDHN_I:%.*]] = add <2 x i64> [[TMP2]], [[TMP3]] -// CHECK-NEXT: [[VADDHN1_I:%.*]] = lshr <2 x i64> [[VADDHN_I]], splat (i64 32) -// CHECK-NEXT: [[VADDHN2_I:%.*]] = trunc <2 x i64> [[VADDHN1_I]] to <2 x i32> -// CHECK-NEXT: ret <2 x i32> [[VADDHN2_I]] -// -uint32x2_t test_vaddhn_u64(uint64x2_t a, uint64x2_t b) { - return vaddhn_u64(a, b); -} - -// CHECK-LABEL: define dso_local <16 x i8> @test_vaddhn_high_s16( -// CHECK-SAME: <8 x i8> noundef [[R:%.*]], <8 x i16> noundef [[A:%.*]], <8 x i16> noundef [[B:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <8 x i16> [[A]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i16> [[B]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16> -// CHECK-NEXT: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16> -// CHECK-NEXT: [[VADDHN_I_I:%.*]] = add <8 x i16> [[TMP2]], [[TMP3]] -// CHECK-NEXT: [[VADDHN1_I_I:%.*]] = lshr <8 x i16> [[VADDHN_I_I]], splat (i16 8) -// CHECK-NEXT: [[VADDHN2_I_I:%.*]] = trunc <8 x i16> [[VADDHN1_I_I]] to <8 x i8> -// CHECK-NEXT: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i8> [[R]], <8 x i8> [[VADDHN2_I_I]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15> -// CHECK-NEXT: ret <16 x i8> [[SHUFFLE_I_I]] -// -int8x16_t test_vaddhn_high_s16(int8x8_t r, int16x8_t a, int16x8_t b) { - return vaddhn_high_s16(r, a, b); -} - -// CHECK-LABEL: define dso_local <8 x i16> @test_vaddhn_high_s32( -// CHECK-SAME: <4 x i16> noundef [[R:%.*]], <4 x i32> noundef [[A:%.*]], <4 x i32> noundef [[B:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32> -// CHECK-NEXT: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32> -// CHECK-NEXT: [[VADDHN_I_I:%.*]] = add <4 x i32> [[TMP2]], [[TMP3]] -// CHECK-NEXT: [[VADDHN1_I_I:%.*]] = lshr <4 x i32> [[VADDHN_I_I]], splat (i32 16) -// CHECK-NEXT: [[VADDHN2_I_I:%.*]] = trunc <4 x i32> [[VADDHN1_I_I]] to <4 x i16> -// CHECK-NEXT: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i16> [[R]], <4 x i16> [[VADDHN2_I_I]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> -// CHECK-NEXT: ret <8 x i16> [[SHUFFLE_I_I]] -// -int16x8_t test_vaddhn_high_s32(int16x4_t r, int32x4_t a, int32x4_t b) { - return vaddhn_high_s32(r, a, b); -} - -// CHECK-LABEL: define dso_local <4 x i32> @test_vaddhn_high_s64( -// CHECK-SAME: <2 x i32> noundef [[R:%.*]], <2 x i64> noundef [[A:%.*]], <2 x i64> noundef [[B:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x i64> [[A]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x i64> [[B]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64> -// CHECK-NEXT: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64> -// CHECK-NEXT: [[VADDHN_I_I:%.*]] = add <2 x i64> [[TMP2]], [[TMP3]] -// CHECK-NEXT: [[VADDHN1_I_I:%.*]] = lshr <2 x i64> [[VADDHN_I_I]], splat (i64 32) -// CHECK-NEXT: [[VADDHN2_I_I:%.*]] = trunc <2 x i64> [[VADDHN1_I_I]] to <2 x i32> -// CHECK-NEXT: [[SHUFFLE_I_I:%.*]] = shufflevector <2 x i32> [[R]], <2 x i32> [[VADDHN2_I_I]], <4 x i32> <i32 0, i32 1, i32 2, i32 3> -// CHECK-NEXT: ret <4 x i32> [[SHUFFLE_I_I]] -// -int32x4_t test_vaddhn_high_s64(int32x2_t r, int64x2_t a, int64x2_t b) { - return vaddhn_high_s64(r, a, b); -} - -// CHECK-LABEL: define dso_local <16 x i8> @test_vaddhn_high_u16( -// CHECK-SAME: <8 x i8> noundef [[R:%.*]], <8 x i16> noundef [[A:%.*]], <8 x i16> noundef [[B:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <8 x i16> [[A]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i16> [[B]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16> -// CHECK-NEXT: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16> -// CHECK-NEXT: [[VADDHN_I_I:%.*]] = add <8 x i16> [[TMP2]], [[TMP3]] -// CHECK-NEXT: [[VADDHN1_I_I:%.*]] = lshr <8 x i16> [[VADDHN_I_I]], splat (i16 8) -// CHECK-NEXT: [[VADDHN2_I_I:%.*]] = trunc <8 x i16> [[VADDHN1_I_I]] to <8 x i8> -// CHECK-NEXT: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i8> [[R]], <8 x i8> [[VADDHN2_I_I]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15> -// CHECK-NEXT: ret <16 x i8> [[SHUFFLE_I_I]] -// -uint8x16_t test_vaddhn_high_u16(uint8x8_t r, uint16x8_t a, uint16x8_t b) { - return vaddhn_high_u16(r, a, b); -} - -// CHECK-LABEL: define dso_local <8 x i16> @test_vaddhn_high_u32( -// CHECK-SAME: <4 x i16> noundef [[R:%.*]], <4 x i32> noundef [[A:%.*]], <4 x i32> noundef [[B:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32> -// CHECK-NEXT: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32> -// CHECK-NEXT: [[VADDHN_I_I:%.*]] = add <4 x i32> [[TMP2]], [[TMP3]] -// CHECK-NEXT: [[VADDHN1_I_I:%.*]] = lshr <4 x i32> [[VADDHN_I_I]], splat (i32 16) -// CHECK-NEXT: [[VADDHN2_I_I:%.*]] = trunc <4 x i32> [[VADDHN1_I_I]] to <4 x i16> -// CHECK-NEXT: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i16> [[R]], <4 x i16> [[VADDHN2_I_I]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> -// CHECK-NEXT: ret <8 x i16> [[SHUFFLE_I_I]] -// -uint16x8_t test_vaddhn_high_u32(uint16x4_t r, uint32x4_t a, uint32x4_t b) { - return vaddhn_high_u32(r, a, b); -} - -// CHECK-LABEL: define dso_local <4 x i32> @test_vaddhn_high_u64( -// CHECK-SAME: <2 x i32> noundef [[R:%.*]], <2 x i64> noundef [[A:%.*]], <2 x i64> noundef [[B:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x i64> [[A]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x i64> [[B]] to <16 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64> -// CHECK-NEXT: [[TMP3:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64> -// CHECK-NEXT: [[VADDHN_I_I:%.*]] = add <2 x i64> [[TMP2]], [[TMP3]] -// CHECK-NEXT: [[VADDHN1_I_I:%.*]] = lshr <2 x i64> [[VADDHN_I_I]], splat (i64 32) -// CHECK-NEXT: [[VADDHN2_I_I:%.*]] = trunc <2 x i64> [[VADDHN1_I_I]] to <2 x i32> -// CHECK-NEXT: [[SHUFFLE_I_I:%.*]] = shufflevector <2 x i32> [[R]], <2 x i32> [[VADDHN2_I_I]], <4 x i32> <i32 0, i32 1, i32 2, i32 3> -// CHECK-NEXT: ret <4 x i32> [[SHUFFLE_I_I]] -// -uint32x4_t test_vaddhn_high_u64(uint32x2_t r, uint64x2_t a, uint64x2_t b) { - return vaddhn_high_u64(r, a, b); -} - -// CHECK-LABEL: define dso_local <8 x i8> @test_vraddhn_s16( -// CHECK-SAME: <8 x i16> noundef [[A:%.*]], <8 x i16> noundef [[B:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <8 x i16> [[A]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i16> [[B]] to <16 x i8> -// CHECK-NEXT: [[VRADDHN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16> -// CHECK-NEXT: [[VRADDHN_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16> -// CHECK-NEXT: [[VRADDHN_V2_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.raddhn.v8i8(<8 x i16> [[VRADDHN_V_I]], <8 x i16> [[VRADDHN_V1_I]]) -// CHECK-NEXT: ret <8 x i8> [[VRADDHN_V2_I]] -// -int8x8_t test_vraddhn_s16(int16x8_t a, int16x8_t b) { - return vraddhn_s16(a, b); -} - -// CHECK-LABEL: define dso_local <4 x i16> @test_vraddhn_s32( -// CHECK-SAME: <4 x i32> noundef [[A:%.*]], <4 x i32> noundef [[B:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B]] to <16 x i8> -// CHECK-NEXT: [[VRADDHN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32> -// CHECK-NEXT: [[VRADDHN_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32> -// CHECK-NEXT: [[VRADDHN_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.raddhn.v4i16(<4 x i32> [[VRADDHN_V_I]], <4 x i32> [[VRADDHN_V1_I]]) -// CHECK-NEXT: [[VRADDHN_V3_I:%.*]] = bitcast <4 x i16> [[VRADDHN_V2_I]] to <8 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[VRADDHN_V3_I]] to <4 x i16> -// CHECK-NEXT: ret <4 x i16> [[TMP2]] -// -int16x4_t test_vraddhn_s32(int32x4_t a, int32x4_t b) { - return vraddhn_s32(a, b); -} - -// CHECK-LABEL: define dso_local <2 x i32> @test_vraddhn_s64( -// CHECK-SAME: <2 x i64> noundef [[A:%.*]], <2 x i64> noundef [[B:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x i64> [[A]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x i64> [[B]] to <16 x i8> -// CHECK-NEXT: [[VRADDHN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64> -// CHECK-NEXT: [[VRADDHN_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64> -// CHECK-NEXT: [[VRADDHN_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.raddhn.v2i32(<2 x i64> [[VRADDHN_V_I]], <2 x i64> [[VRADDHN_V1_I]]) -// CHECK-NEXT: [[VRADDHN_V3_I:%.*]] = bitcast <2 x i32> [[VRADDHN_V2_I]] to <8 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[VRADDHN_V3_I]] to <2 x i32> -// CHECK-NEXT: ret <2 x i32> [[TMP2]] -// -int32x2_t test_vraddhn_s64(int64x2_t a, int64x2_t b) { - return vraddhn_s64(a, b); -} - -// CHECK-LABEL: define dso_local <8 x i8> @test_vraddhn_u16( -// CHECK-SAME: <8 x i16> noundef [[A:%.*]], <8 x i16> noundef [[B:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <8 x i16> [[A]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i16> [[B]] to <16 x i8> -// CHECK-NEXT: [[VRADDHN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16> -// CHECK-NEXT: [[VRADDHN_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16> -// CHECK-NEXT: [[VRADDHN_V2_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.raddhn.v8i8(<8 x i16> [[VRADDHN_V_I]], <8 x i16> [[VRADDHN_V1_I]]) -// CHECK-NEXT: ret <8 x i8> [[VRADDHN_V2_I]] -// -uint8x8_t test_vraddhn_u16(uint16x8_t a, uint16x8_t b) { - return vraddhn_u16(a, b); -} - -// CHECK-LABEL: define dso_local <4 x i16> @test_vraddhn_u32( -// CHECK-SAME: <4 x i32> noundef [[A:%.*]], <4 x i32> noundef [[B:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B]] to <16 x i8> -// CHECK-NEXT: [[VRADDHN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32> -// CHECK-NEXT: [[VRADDHN_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32> -// CHECK-NEXT: [[VRADDHN_V2_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.raddhn.v4i16(<4 x i32> [[VRADDHN_V_I]], <4 x i32> [[VRADDHN_V1_I]]) -// CHECK-NEXT: [[VRADDHN_V3_I:%.*]] = bitcast <4 x i16> [[VRADDHN_V2_I]] to <8 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[VRADDHN_V3_I]] to <4 x i16> -// CHECK-NEXT: ret <4 x i16> [[TMP2]] -// -uint16x4_t test_vraddhn_u32(uint32x4_t a, uint32x4_t b) { - return vraddhn_u32(a, b); -} - -// CHECK-LABEL: define dso_local <2 x i32> @test_vraddhn_u64( -// CHECK-SAME: <2 x i64> noundef [[A:%.*]], <2 x i64> noundef [[B:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x i64> [[A]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x i64> [[B]] to <16 x i8> -// CHECK-NEXT: [[VRADDHN_V_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64> -// CHECK-NEXT: [[VRADDHN_V1_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64> -// CHECK-NEXT: [[VRADDHN_V2_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.raddhn.v2i32(<2 x i64> [[VRADDHN_V_I]], <2 x i64> [[VRADDHN_V1_I]]) -// CHECK-NEXT: [[VRADDHN_V3_I:%.*]] = bitcast <2 x i32> [[VRADDHN_V2_I]] to <8 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[VRADDHN_V3_I]] to <2 x i32> -// CHECK-NEXT: ret <2 x i32> [[TMP2]] -// -uint32x2_t test_vraddhn_u64(uint64x2_t a, uint64x2_t b) { - return vraddhn_u64(a, b); -} - -// CHECK-LABEL: define dso_local <16 x i8> @test_vraddhn_high_s16( -// CHECK-SAME: <8 x i8> noundef [[R:%.*]], <8 x i16> noundef [[A:%.*]], <8 x i16> noundef [[B:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <8 x i16> [[A]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i16> [[B]] to <16 x i8> -// CHECK-NEXT: [[VRADDHN_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16> -// CHECK-NEXT: [[VRADDHN_V1_I_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16> -// CHECK-NEXT: [[VRADDHN_V2_I_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.raddhn.v8i8(<8 x i16> [[VRADDHN_V_I_I]], <8 x i16> [[VRADDHN_V1_I_I]]) -// CHECK-NEXT: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i8> [[R]], <8 x i8> [[VRADDHN_V2_I_I]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15> -// CHECK-NEXT: ret <16 x i8> [[SHUFFLE_I_I]] -// -int8x16_t test_vraddhn_high_s16(int8x8_t r, int16x8_t a, int16x8_t b) { - return vraddhn_high_s16(r, a, b); -} - -// CHECK-LABEL: define dso_local <8 x i16> @test_vraddhn_high_s32( -// CHECK-SAME: <4 x i16> noundef [[R:%.*]], <4 x i32> noundef [[A:%.*]], <4 x i32> noundef [[B:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B]] to <16 x i8> -// CHECK-NEXT: [[VRADDHN_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32> -// CHECK-NEXT: [[VRADDHN_V1_I_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32> -// CHECK-NEXT: [[VRADDHN_V2_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.raddhn.v4i16(<4 x i32> [[VRADDHN_V_I_I]], <4 x i32> [[VRADDHN_V1_I_I]]) -// CHECK-NEXT: [[VRADDHN_V3_I_I:%.*]] = bitcast <4 x i16> [[VRADDHN_V2_I_I]] to <8 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[VRADDHN_V3_I_I]] to <4 x i16> -// CHECK-NEXT: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i16> [[R]], <4 x i16> [[TMP2]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> -// CHECK-NEXT: ret <8 x i16> [[SHUFFLE_I_I]] -// -int16x8_t test_vraddhn_high_s32(int16x4_t r, int32x4_t a, int32x4_t b) { - return vraddhn_high_s32(r, a, b); -} - -// CHECK-LABEL: define dso_local <4 x i32> @test_vraddhn_high_s64( -// CHECK-SAME: <2 x i32> noundef [[R:%.*]], <2 x i64> noundef [[A:%.*]], <2 x i64> noundef [[B:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x i64> [[A]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x i64> [[B]] to <16 x i8> -// CHECK-NEXT: [[VRADDHN_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64> -// CHECK-NEXT: [[VRADDHN_V1_I_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64> -// CHECK-NEXT: [[VRADDHN_V2_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.raddhn.v2i32(<2 x i64> [[VRADDHN_V_I_I]], <2 x i64> [[VRADDHN_V1_I_I]]) -// CHECK-NEXT: [[VRADDHN_V3_I_I:%.*]] = bitcast <2 x i32> [[VRADDHN_V2_I_I]] to <8 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[VRADDHN_V3_I_I]] to <2 x i32> -// CHECK-NEXT: [[SHUFFLE_I_I:%.*]] = shufflevector <2 x i32> [[R]], <2 x i32> [[TMP2]], <4 x i32> <i32 0, i32 1, i32 2, i32 3> -// CHECK-NEXT: ret <4 x i32> [[SHUFFLE_I_I]] -// -int32x4_t test_vraddhn_high_s64(int32x2_t r, int64x2_t a, int64x2_t b) { - return vraddhn_high_s64(r, a, b); -} - -// CHECK-LABEL: define dso_local <16 x i8> @test_vraddhn_high_u16( -// CHECK-SAME: <8 x i8> noundef [[R:%.*]], <8 x i16> noundef [[A:%.*]], <8 x i16> noundef [[B:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <8 x i16> [[A]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i16> [[B]] to <16 x i8> -// CHECK-NEXT: [[VRADDHN_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <8 x i16> -// CHECK-NEXT: [[VRADDHN_V1_I_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <8 x i16> -// CHECK-NEXT: [[VRADDHN_V2_I_I:%.*]] = call <8 x i8> @llvm.aarch64.neon.raddhn.v8i8(<8 x i16> [[VRADDHN_V_I_I]], <8 x i16> [[VRADDHN_V1_I_I]]) -// CHECK-NEXT: [[SHUFFLE_I_I:%.*]] = shufflevector <8 x i8> [[R]], <8 x i8> [[VRADDHN_V2_I_I]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15> -// CHECK-NEXT: ret <16 x i8> [[SHUFFLE_I_I]] -// -uint8x16_t test_vraddhn_high_u16(uint8x8_t r, uint16x8_t a, uint16x8_t b) { - return vraddhn_high_u16(r, a, b); -} - -// CHECK-LABEL: define dso_local <8 x i16> @test_vraddhn_high_u32( -// CHECK-SAME: <4 x i16> noundef [[R:%.*]], <4 x i32> noundef [[A:%.*]], <4 x i32> noundef [[B:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[B]] to <16 x i8> -// CHECK-NEXT: [[VRADDHN_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <4 x i32> -// CHECK-NEXT: [[VRADDHN_V1_I_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32> -// CHECK-NEXT: [[VRADDHN_V2_I_I:%.*]] = call <4 x i16> @llvm.aarch64.neon.raddhn.v4i16(<4 x i32> [[VRADDHN_V_I_I]], <4 x i32> [[VRADDHN_V1_I_I]]) -// CHECK-NEXT: [[VRADDHN_V3_I_I:%.*]] = bitcast <4 x i16> [[VRADDHN_V2_I_I]] to <8 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[VRADDHN_V3_I_I]] to <4 x i16> -// CHECK-NEXT: [[SHUFFLE_I_I:%.*]] = shufflevector <4 x i16> [[R]], <4 x i16> [[TMP2]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> -// CHECK-NEXT: ret <8 x i16> [[SHUFFLE_I_I]] -// -uint16x8_t test_vraddhn_high_u32(uint16x4_t r, uint32x4_t a, uint32x4_t b) { - return vraddhn_high_u32(r, a, b); -} - -// CHECK-LABEL: define dso_local <4 x i32> @test_vraddhn_high_u64( -// CHECK-SAME: <2 x i32> noundef [[R:%.*]], <2 x i64> noundef [[A:%.*]], <2 x i64> noundef [[B:%.*]]) #[[ATTR0]] { -// CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x i64> [[A]] to <16 x i8> -// CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x i64> [[B]] to <16 x i8> -// CHECK-NEXT: [[VRADDHN_V_I_I:%.*]] = bitcast <16 x i8> [[TMP0]] to <2 x i64> -// CHECK-NEXT: [[VRADDHN_V1_I_I:%.*]] = bitcast <16 x i8> [[TMP1]] to <2 x i64> -// CHECK-NEXT: [[VRADDHN_V2_I_I:%.*]] = call <2 x i32> @llvm.aarch64.neon.raddhn.v2i32(<2 x i64> [[VRADDHN_V_I_I]], <2 x i64> [[VRADDHN_V1_I_I]]) -// CHECK-NEXT: [[VRADDHN_V3_I_I:%.*]] = bitcast <2 x i32> [[VRADDHN_V2_I_I]] to <8 x i8> -// CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[VRADDHN_V3_I_I]] to <2 x i32> -// CHECK-NEXT: [[SHUFFLE_I_I:%.*]] = shufflevector <2 x i32> [[R]], <2 x i32> [[TMP2]], <4 x i32> <i32 0, i32 1, i32 2, i32 3> -// CHECK-NEXT: ret <4 x i32> [[SHUFFLE_I_I]] -// -uint32x4_t test_vraddhn_high_u64(uint32x2_t r, uint64x2_t a, uint64x2_t b) { - return vraddhn_high_u64(r, a, b); -} - // CHECK-LABEL: define dso_local <8 x i8> @test_vsubhn_s16( // CHECK-SAME: <8 x i16> noundef [[A:%.*]], <8 x i16> noundef [[B:%.*]]) #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] diff --git a/clang/test/CodeGen/AArch64/neon/add.c b/clang/test/CodeGen/AArch64/neon/add.c index b1dc5c253e7d6..7e557dd905068 100644 --- a/clang/test/CodeGen/AArch64/neon/add.c +++ b/clang/test/CodeGen/AArch64/neon/add.c @@ -3,6 +3,9 @@ // RUN: %clang_cc1_cg_arm64_neon -emit-llvm %s -disable-O0-optnone | opt -S -passes=mem2reg,sroa | FileCheck %s --check-prefix=LLVM // RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon -fclangir -emit-llvm %s -disable-O0-optnone | opt -S -passes=mem2reg,sroa | FileCheck %s --check-prefix=LLVM %} // RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon -fclangir -emit-cir %s -disable-O0-optnone | FileCheck %s --check-prefix=CIR %} +// Narrowing-addition checks use instcombine to fold no-op bitcasts (LLVM-IC prefix). +// RUN: %clang_cc1_cg_arm64_neon -emit-llvm %s -disable-O0-optnone | opt -S -passes=mem2reg,sroa,instcombine | FileCheck %s --check-prefix=LLVM-IC +// RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon -fclangir -emit-llvm %s -disable-O0-optnone | opt -S -passes=mem2reg,sroa,instcombine | FileCheck %s --check-prefix=LLVM-IC %} #include <arm_neon.h> @@ -720,3 +723,596 @@ uint64x2_t test_vaddw_high_u32(uint64x2_t a, uint32x4_t b) { // LLVM-NEXT: ret <2 x i64> [[ADD_I]] return vaddw_high_u32(a, b); } + +//===----------------------------------------------------------------------===// +// 2.1.1.1.3. Narrowing addition +// https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#narrowing-addition +//===----------------------------------------------------------------------===// + +// LLVM-IC-LABEL: @test_vhadd_s8( +// LLVM-IC-SAME: <8 x i8> {{.*}}[[V1:%.*]], <8 x i8> {{.*}}[[V2:%.*]]) +// CIR-LABEL: @vhadd_s8( +int8x8_t test_vhadd_s8(int8x8_t v1, int8x8_t v2) { + // CIR: cir.call_llvm_intrinsic "aarch64.neon.shadd" + + // LLVM-IC: [[RES:%.*]] = call <8 x i8> @llvm.aarch64.neon.shadd.v8i8(<8 x i8> [[V1]], <8 x i8> [[V2]]) + // LLVM-IC: ret <8 x i8> [[RES]] + return vhadd_s8(v1, v2); +} + +// LLVM-IC-LABEL: @test_vhadd_s16( +// LLVM-IC-SAME: <4 x i16> {{.*}}[[V1:%.*]], <4 x i16> {{.*}}[[V2:%.*]]) +// CIR-LABEL: @vhadd_s16( +int16x4_t test_vhadd_s16(int16x4_t v1, int16x4_t v2) { + // CIR: cir.call_llvm_intrinsic "aarch64.neon.shadd" + + // LLVM-IC: [[RES:%.*]] = call <4 x i16> @llvm.aarch64.neon.shadd.v4i16(<4 x i16> [[V1]], <4 x i16> [[V2]]) + // LLVM-IC: ret <4 x i16> [[RES]] + return vhadd_s16(v1, v2); +} + +// LLVM-IC-LABEL: @test_vhadd_s32( +// LLVM-IC-SAME: <2 x i32> {{.*}}[[V1:%.*]], <2 x i32> {{.*}}[[V2:%.*]]) +// CIR-LABEL: @vhadd_s32( +int32x2_t test_vhadd_s32(int32x2_t v1, int32x2_t v2) { + // CIR: cir.call_llvm_intrinsic "aarch64.neon.shadd" + + // LLVM-IC: [[RES:%.*]] = call <2 x i32> @llvm.aarch64.neon.shadd.v2i32(<2 x i32> [[V1]], <2 x i32> [[V2]]) + // LLVM-IC: ret <2 x i32> [[RES]] + return vhadd_s32(v1, v2); +} + +// LLVM-IC-LABEL: @test_vhadd_u8( +// LLVM-IC-SAME: <8 x i8> {{.*}}[[V1:%.*]], <8 x i8> {{.*}}[[V2:%.*]]) +// CIR-LABEL: @vhadd_u8( +uint8x8_t test_vhadd_u8(uint8x8_t v1, uint8x8_t v2) { + // CIR: cir.call_llvm_intrinsic "aarch64.neon.uhadd" + + // LLVM-IC: [[RES:%.*]] = call <8 x i8> @llvm.aarch64.neon.uhadd.v8i8(<8 x i8> [[V1]], <8 x i8> [[V2]]) + // LLVM-IC: ret <8 x i8> [[RES]] + return vhadd_u8(v1, v2); +} + +// LLVM-IC-LABEL: @test_vhadd_u16( +// LLVM-IC-SAME: <4 x i16> {{.*}}[[V1:%.*]], <4 x i16> {{.*}}[[V2:%.*]]) +// CIR-LABEL: @vhadd_u16( +uint16x4_t test_vhadd_u16(uint16x4_t v1, uint16x4_t v2) { + // CIR: cir.call_llvm_intrinsic "aarch64.neon.uhadd" + + // LLVM-IC: [[RES:%.*]] = call <4 x i16> @llvm.aarch64.neon.uhadd.v4i16(<4 x i16> [[V1]], <4 x i16> [[V2]]) + // LLVM-IC: ret <4 x i16> [[RES]] + return vhadd_u16(v1, v2); +} + +// LLVM-IC-LABEL: @test_vhadd_u32( +// LLVM-IC-SAME: <2 x i32> {{.*}}[[V1:%.*]], <2 x i32> {{.*}}[[V2:%.*]]) +// CIR-LABEL: @vhadd_u32( +uint32x2_t test_vhadd_u32(uint32x2_t v1, uint32x2_t v2) { + // CIR: cir.call_llvm_intrinsic "aarch64.neon.uhadd" + + // LLVM-IC: [[RES:%.*]] = call <2 x i32> @llvm.aarch64.neon.uhadd.v2i32(<2 x i32> [[V1]], <2 x i32> [[V2]]) + // LLVM-IC: ret <2 x i32> [[RES]] + return vhadd_u32(v1, v2); +} + +// LLVM-IC-LABEL: @test_vhaddq_s8( +// LLVM-IC-SAME: <16 x i8> {{.*}}[[V1:%.*]], <16 x i8> {{.*}}[[V2:%.*]]) +// CIR-LABEL: @vhaddq_s8( +int8x16_t test_vhaddq_s8(int8x16_t v1, int8x16_t v2) { + // CIR: cir.call_llvm_intrinsic "aarch64.neon.shadd" + + // LLVM-IC: [[RES:%.*]] = call <16 x i8> @llvm.aarch64.neon.shadd.v16i8(<16 x i8> [[V1]], <16 x i8> [[V2]]) + // LLVM-IC: ret <16 x i8> [[RES]] + return vhaddq_s8(v1, v2); +} + +// LLVM-IC-LABEL: @test_vhaddq_s16( +// LLVM-IC-SAME: <8 x i16> {{.*}}[[V1:%.*]], <8 x i16> {{.*}}[[V2:%.*]]) +// CIR-LABEL: @vhaddq_s16( +int16x8_t test_vhaddq_s16(int16x8_t v1, int16x8_t v2) { + // CIR: cir.call_llvm_intrinsic "aarch64.neon.shadd" + + // LLVM-IC: [[RES:%.*]] = call <8 x i16> @llvm.aarch64.neon.shadd.v8i16(<8 x i16> [[V1]], <8 x i16> [[V2]]) + // LLVM-IC: ret <8 x i16> [[RES]] + return vhaddq_s16(v1, v2); +} + +// LLVM-IC-LABEL: @test_vhaddq_s32( +// LLVM-IC-SAME: <4 x i32> {{.*}}[[V1:%.*]], <4 x i32> {{.*}}[[V2:%.*]]) +// CIR-LABEL: @vhaddq_s32( +int32x4_t test_vhaddq_s32(int32x4_t v1, int32x4_t v2) { + // CIR: cir.call_llvm_intrinsic "aarch64.neon.shadd" + + // LLVM-IC: [[RES:%.*]] = call <4 x i32> @llvm.aarch64.neon.shadd.v4i32(<4 x i32> [[V1]], <4 x i32> [[V2]]) + // LLVM-IC: ret <4 x i32> [[RES]] + return vhaddq_s32(v1, v2); +} + +// LLVM-IC-LABEL: @test_vhaddq_u8( +// LLVM-IC-SAME: <16 x i8> {{.*}}[[V1:%.*]], <16 x i8> {{.*}}[[V2:%.*]]) +// CIR-LABEL: @vhaddq_u8( +uint8x16_t test_vhaddq_u8(uint8x16_t v1, uint8x16_t v2) { + // CIR: cir.call_llvm_intrinsic "aarch64.neon.uhadd" + + // LLVM-IC: [[RES:%.*]] = call <16 x i8> @llvm.aarch64.neon.uhadd.v16i8(<16 x i8> [[V1]], <16 x i8> [[V2]]) + // LLVM-IC: ret <16 x i8> [[RES]] + return vhaddq_u8(v1, v2); +} + +// LLVM-IC-LABEL: @test_vhaddq_u16( +// LLVM-IC-SAME: <8 x i16> {{.*}}[[V1:%.*]], <8 x i16> {{.*}}[[V2:%.*]]) +// CIR-LABEL: @vhaddq_u16( +uint16x8_t test_vhaddq_u16(uint16x8_t v1, uint16x8_t v2) { + // CIR: cir.call_llvm_intrinsic "aarch64.neon.uhadd" + + // LLVM-IC: [[RES:%.*]] = call <8 x i16> @llvm.aarch64.neon.uhadd.v8i16(<8 x i16> [[V1]], <8 x i16> [[V2]]) + // LLVM-IC: ret <8 x i16> [[RES]] + return vhaddq_u16(v1, v2); +} + +// LLVM-IC-LABEL: @test_vhaddq_u32( +// LLVM-IC-SAME: <4 x i32> {{.*}}[[V1:%.*]], <4 x i32> {{.*}}[[V2:%.*]]) +// CIR-LABEL: @vhaddq_u32( +uint32x4_t test_vhaddq_u32(uint32x4_t v1, uint32x4_t v2) { + // CIR: cir.call_llvm_intrinsic "aarch64.neon.uhadd" + + // LLVM-IC: [[RES:%.*]] = call <4 x i32> @llvm.aarch64.neon.uhadd.v4i32(<4 x i32> [[V1]], <4 x i32> [[V2]]) + // LLVM-IC: ret <4 x i32> [[RES]] + return vhaddq_u32(v1, v2); +} + +// LLVM-IC-LABEL: @test_vrhadd_s8( +// LLVM-IC-SAME: <8 x i8> {{.*}}[[V1:%.*]], <8 x i8> {{.*}}[[V2:%.*]]) +// CIR-LABEL: @vrhadd_s8( +int8x8_t test_vrhadd_s8(int8x8_t v1, int8x8_t v2) { + // CIR: cir.call_llvm_intrinsic "aarch64.neon.srhadd" + + // LLVM-IC: [[RES:%.*]] = call <8 x i8> @llvm.aarch64.neon.srhadd.v8i8(<8 x i8> [[V1]], <8 x i8> [[V2]]) + // LLVM-IC: ret <8 x i8> [[RES]] + return vrhadd_s8(v1, v2); +} + +// LLVM-IC-LABEL: @test_vrhadd_s16( +// LLVM-IC-SAME: <4 x i16> {{.*}}[[V1:%.*]], <4 x i16> {{.*}}[[V2:%.*]]) +// CIR-LABEL: @vrhadd_s16( +int16x4_t test_vrhadd_s16(int16x4_t v1, int16x4_t v2) { + // CIR: cir.call_llvm_intrinsic "aarch64.neon.srhadd" + + // LLVM-IC: [[RES:%.*]] = call <4 x i16> @llvm.aarch64.neon.srhadd.v4i16(<4 x i16> [[V1]], <4 x i16> [[V2]]) + // LLVM-IC: ret <4 x i16> [[RES]] + return vrhadd_s16(v1, v2); +} + +// LLVM-IC-LABEL: @test_vrhadd_s32( +// LLVM-IC-SAME: <2 x i32> {{.*}}[[V1:%.*]], <2 x i32> {{.*}}[[V2:%.*]]) +// CIR-LABEL: @vrhadd_s32( +int32x2_t test_vrhadd_s32(int32x2_t v1, int32x2_t v2) { + // CIR: cir.call_llvm_intrinsic "aarch64.neon.srhadd" + + // LLVM-IC: [[RES:%.*]] = call <2 x i32> @llvm.aarch64.neon.srhadd.v2i32(<2 x i32> [[V1]], <2 x i32> [[V2]]) + // LLVM-IC: ret <2 x i32> [[RES]] + return vrhadd_s32(v1, v2); +} + +// LLVM-IC-LABEL: @test_vrhadd_u8( +// LLVM-IC-SAME: <8 x i8> {{.*}}[[V1:%.*]], <8 x i8> {{.*}}[[V2:%.*]]) +// CIR-LABEL: @vrhadd_u8( +uint8x8_t test_vrhadd_u8(uint8x8_t v1, uint8x8_t v2) { + // CIR: cir.call_llvm_intrinsic "aarch64.neon.urhadd" + + // LLVM-IC: [[RES:%.*]] = call <8 x i8> @llvm.aarch64.neon.urhadd.v8i8(<8 x i8> [[V1]], <8 x i8> [[V2]]) + // LLVM-IC: ret <8 x i8> [[RES]] + return vrhadd_u8(v1, v2); +} + +// LLVM-IC-LABEL: @test_vrhadd_u16( +// LLVM-IC-SAME: <4 x i16> {{.*}}[[V1:%.*]], <4 x i16> {{.*}}[[V2:%.*]]) +// CIR-LABEL: @vrhadd_u16( +uint16x4_t test_vrhadd_u16(uint16x4_t v1, uint16x4_t v2) { + // CIR: cir.call_llvm_intrinsic "aarch64.neon.urhadd" + + // LLVM-IC: [[RES:%.*]] = call <4 x i16> @llvm.aarch64.neon.urhadd.v4i16(<4 x i16> [[V1]], <4 x i16> [[V2]]) + // LLVM-IC: ret <4 x i16> [[RES]] + return vrhadd_u16(v1, v2); +} + +// LLVM-IC-LABEL: @test_vrhadd_u32( +// LLVM-IC-SAME: <2 x i32> {{.*}}[[V1:%.*]], <2 x i32> {{.*}}[[V2:%.*]]) +// CIR-LABEL: @vrhadd_u32( +uint32x2_t test_vrhadd_u32(uint32x2_t v1, uint32x2_t v2) { + // CIR: cir.call_llvm_intrinsic "aarch64.neon.urhadd" + + // LLVM-IC: [[RES:%.*]] = call <2 x i32> @llvm.aarch64.neon.urhadd.v2i32(<2 x i32> [[V1]], <2 x i32> [[V2]]) + // LLVM-IC: ret <2 x i32> [[RES]] + return vrhadd_u32(v1, v2); +} + +// LLVM-IC-LABEL: @test_vrhaddq_s8( +// LLVM-IC-SAME: <16 x i8> {{.*}}[[V1:%.*]], <16 x i8> {{.*}}[[V2:%.*]]) +// CIR-LABEL: @vrhaddq_s8( +int8x16_t test_vrhaddq_s8(int8x16_t v1, int8x16_t v2) { + // CIR: cir.call_llvm_intrinsic "aarch64.neon.srhadd" + + // LLVM-IC: [[RES:%.*]] = call <16 x i8> @llvm.aarch64.neon.srhadd.v16i8(<16 x i8> [[V1]], <16 x i8> [[V2]]) + // LLVM-IC: ret <16 x i8> [[RES]] + return vrhaddq_s8(v1, v2); +} + +// LLVM-IC-LABEL: @test_vrhaddq_s16( +// LLVM-IC-SAME: <8 x i16> {{.*}}[[V1:%.*]], <8 x i16> {{.*}}[[V2:%.*]]) +// CIR-LABEL: @vrhaddq_s16( +int16x8_t test_vrhaddq_s16(int16x8_t v1, int16x8_t v2) { + // CIR: cir.call_llvm_intrinsic "aarch64.neon.srhadd" + + // LLVM-IC: [[RES:%.*]] = call <8 x i16> @llvm.aarch64.neon.srhadd.v8i16(<8 x i16> [[V1]], <8 x i16> [[V2]]) + // LLVM-IC: ret <8 x i16> [[RES]] + return vrhaddq_s16(v1, v2); +} + +// LLVM-IC-LABEL: @test_vrhaddq_s32( +// LLVM-IC-SAME: <4 x i32> {{.*}}[[V1:%.*]], <4 x i32> {{.*}}[[V2:%.*]]) +// CIR-LABEL: @vrhaddq_s32( +int32x4_t test_vrhaddq_s32(int32x4_t v1, int32x4_t v2) { + // CIR: cir.call_llvm_intrinsic "aarch64.neon.srhadd" + + // LLVM-IC: [[RES:%.*]] = call <4 x i32> @llvm.aarch64.neon.srhadd.v4i32(<4 x i32> [[V1]], <4 x i32> [[V2]]) + // LLVM-IC: ret <4 x i32> [[RES]] + return vrhaddq_s32(v1, v2); +} + +// LLVM-IC-LABEL: @test_vrhaddq_u8( +// LLVM-IC-SAME: <16 x i8> {{.*}}[[V1:%.*]], <16 x i8> {{.*}}[[V2:%.*]]) +// CIR-LABEL: @vrhaddq_u8( +uint8x16_t test_vrhaddq_u8(uint8x16_t v1, uint8x16_t v2) { + // CIR: cir.call_llvm_intrinsic "aarch64.neon.urhadd" + + // LLVM-IC: [[RES:%.*]] = call <16 x i8> @llvm.aarch64.neon.urhadd.v16i8(<16 x i8> [[V1]], <16 x i8> [[V2]]) + // LLVM-IC: ret <16 x i8> [[RES]] + return vrhaddq_u8(v1, v2); +} + +// LLVM-IC-LABEL: @test_vrhaddq_u16( +// LLVM-IC-SAME: <8 x i16> {{.*}}[[V1:%.*]], <8 x i16> {{.*}}[[V2:%.*]]) +// CIR-LABEL: @vrhaddq_u16( +uint16x8_t test_vrhaddq_u16(uint16x8_t v1, uint16x8_t v2) { + // CIR: cir.call_llvm_intrinsic "aarch64.neon.urhadd" + + // LLVM-IC: [[RES:%.*]] = call <8 x i16> @llvm.aarch64.neon.urhadd.v8i16(<8 x i16> [[V1]], <8 x i16> [[V2]]) + // LLVM-IC: ret <8 x i16> [[RES]] + return vrhaddq_u16(v1, v2); +} + +// LLVM-IC-LABEL: @test_vrhaddq_u32( +// LLVM-IC-SAME: <4 x i32> {{.*}}[[V1:%.*]], <4 x i32> {{.*}}[[V2:%.*]]) +// CIR-LABEL: @vrhaddq_u32( +uint32x4_t test_vrhaddq_u32(uint32x4_t v1, uint32x4_t v2) { + // CIR: cir.call_llvm_intrinsic "aarch64.neon.urhadd" + + // LLVM-IC: [[RES:%.*]] = call <4 x i32> @llvm.aarch64.neon.urhadd.v4i32(<4 x i32> [[V1]], <4 x i32> [[V2]]) + // LLVM-IC: ret <4 x i32> [[RES]] + return vrhaddq_u32(v1, v2); +} + +// LLVM-IC-LABEL: @test_vaddhn_s16( +// LLVM-IC-SAME: <8 x i16> {{.*}}[[A:%.*]], <8 x i16> {{.*}}[[B:%.*]]) +// CIR-LABEL: @vaddhn_s16( +int8x8_t test_vaddhn_s16(int16x8_t a, int16x8_t b) { + // CIR: cir.add + // CIR: cir.shift(right + // CIR: cir.cast integral + + // LLVM-IC: [[ADD:%.*]] = add <8 x i16> [[A]], [[B]] + // LLVM-IC: [[SH:%.*]] = lshr <8 x i16> [[ADD]], splat (i16 8) + // LLVM-IC: [[TR:%.*]] = trunc nuw <8 x i16> [[SH]] to <8 x i8> + // LLVM-IC: ret <8 x i8> [[TR]] + return vaddhn_s16(a, b); +} + +// LLVM-IC-LABEL: @test_vaddhn_s32( +// LLVM-IC-SAME: <4 x i32> {{.*}}[[A:%.*]], <4 x i32> {{.*}}[[B:%.*]]) +// CIR-LABEL: @vaddhn_s32( +int16x4_t test_vaddhn_s32(int32x4_t a, int32x4_t b) { + // CIR: cir.add + // CIR: cir.shift(right + // CIR: cir.cast integral + + // LLVM-IC: [[ADD:%.*]] = add <4 x i32> [[A]], [[B]] + // LLVM-IC: [[SH:%.*]] = lshr <4 x i32> [[ADD]], splat (i32 16) + // LLVM-IC: [[TR:%.*]] = trunc nuw <4 x i32> [[SH]] to <4 x i16> + // LLVM-IC: ret <4 x i16> [[TR]] + return vaddhn_s32(a, b); +} + +// LLVM-IC-LABEL: @test_vaddhn_s64( +// LLVM-IC-SAME: <2 x i64> {{.*}}[[A:%.*]], <2 x i64> {{.*}}[[B:%.*]]) +// CIR-LABEL: @vaddhn_s64( +int32x2_t test_vaddhn_s64(int64x2_t a, int64x2_t b) { + // CIR: cir.add + // CIR: cir.shift(right + // CIR: cir.cast integral + + // LLVM-IC: [[ADD:%.*]] = add <2 x i64> [[A]], [[B]] + // LLVM-IC: [[SH:%.*]] = lshr <2 x i64> [[ADD]], splat (i64 32) + // LLVM-IC: [[TR:%.*]] = trunc nuw <2 x i64> [[SH]] to <2 x i32> + // LLVM-IC: ret <2 x i32> [[TR]] + return vaddhn_s64(a, b); +} + +// LLVM-IC-LABEL: @test_vaddhn_u16( +// LLVM-IC-SAME: <8 x i16> {{.*}}[[A:%.*]], <8 x i16> {{.*}}[[B:%.*]]) +// CIR-LABEL: @vaddhn_u16( +uint8x8_t test_vaddhn_u16(uint16x8_t a, uint16x8_t b) { + // CIR: cir.add + // CIR: cir.shift(right + // CIR: cir.cast integral + + // LLVM-IC: [[ADD:%.*]] = add <8 x i16> [[A]], [[B]] + // LLVM-IC: [[SH:%.*]] = lshr <8 x i16> [[ADD]], splat (i16 8) + // LLVM-IC: [[TR:%.*]] = trunc nuw <8 x i16> [[SH]] to <8 x i8> + // LLVM-IC: ret <8 x i8> [[TR]] + return vaddhn_u16(a, b); +} + +// LLVM-IC-LABEL: @test_vaddhn_u32( +// LLVM-IC-SAME: <4 x i32> {{.*}}[[A:%.*]], <4 x i32> {{.*}}[[B:%.*]]) +// CIR-LABEL: @vaddhn_u32( +uint16x4_t test_vaddhn_u32(uint32x4_t a, uint32x4_t b) { + // CIR: cir.add + // CIR: cir.shift(right + // CIR: cir.cast integral + + // LLVM-IC: [[ADD:%.*]] = add <4 x i32> [[A]], [[B]] + // LLVM-IC: [[SH:%.*]] = lshr <4 x i32> [[ADD]], splat (i32 16) + // LLVM-IC: [[TR:%.*]] = trunc nuw <4 x i32> [[SH]] to <4 x i16> + // LLVM-IC: ret <4 x i16> [[TR]] + return vaddhn_u32(a, b); +} + +// LLVM-IC-LABEL: @test_vaddhn_u64( +// LLVM-IC-SAME: <2 x i64> {{.*}}[[A:%.*]], <2 x i64> {{.*}}[[B:%.*]]) +// CIR-LABEL: @vaddhn_u64( +uint32x2_t test_vaddhn_u64(uint64x2_t a, uint64x2_t b) { + // CIR: cir.add + // CIR: cir.shift(right + // CIR: cir.cast integral + + // LLVM-IC: [[ADD:%.*]] = add <2 x i64> [[A]], [[B]] + // LLVM-IC: [[SH:%.*]] = lshr <2 x i64> [[ADD]], splat (i64 32) + // LLVM-IC: [[TR:%.*]] = trunc nuw <2 x i64> [[SH]] to <2 x i32> + // LLVM-IC: ret <2 x i32> [[TR]] + return vaddhn_u64(a, b); +} + +// LLVM-IC-LABEL: @test_vaddhn_high_s16( +// LLVM-IC-SAME: <8 x i8> {{.*}}[[R:%.*]], <8 x i16> {{.*}}[[A:%.*]], <8 x i16> {{.*}}[[B:%.*]]) +// CIR-LABEL: @vaddhn_high_s16( +int8x16_t test_vaddhn_high_s16(int8x8_t r, int16x8_t a, int16x8_t b) { + // CIR: cir.call @vaddhn_s16( + // CIR: cir.call @vcombine_s8( + + // LLVM-IC: [[ADD:%.*]] = add <8 x i16> [[A]], [[B]] + // LLVM-IC: [[SH:%.*]] = lshr <8 x i16> [[ADD]], splat (i16 8) + // LLVM-IC: [[TR:%.*]] = trunc nuw <8 x i16> [[SH]] to <8 x i8> + // LLVM-IC: [[RES:%.*]] = shufflevector <8 x i8> [[R]], <8 x i8> [[TR]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15> + // LLVM-IC: ret <16 x i8> [[RES]] + return vaddhn_high_s16(r, a, b); +} + +// LLVM-IC-LABEL: @test_vaddhn_high_s32( +// LLVM-IC-SAME: <4 x i16> {{.*}}[[R:%.*]], <4 x i32> {{.*}}[[A:%.*]], <4 x i32> {{.*}}[[B:%.*]]) +// CIR-LABEL: @vaddhn_high_s32( +int16x8_t test_vaddhn_high_s32(int16x4_t r, int32x4_t a, int32x4_t b) { + // CIR: cir.call @vaddhn_s32( + // CIR: cir.call @vcombine_s16( + + // LLVM-IC: [[ADD:%.*]] = add <4 x i32> [[A]], [[B]] + // LLVM-IC: [[SH:%.*]] = lshr <4 x i32> [[ADD]], splat (i32 16) + // LLVM-IC: [[TR:%.*]] = trunc nuw <4 x i32> [[SH]] to <4 x i16> + // LLVM-IC: [[RES:%.*]] = shufflevector <4 x i16> [[R]], <4 x i16> [[TR]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> + // LLVM-IC: ret <8 x i16> [[RES]] + return vaddhn_high_s32(r, a, b); +} + +// LLVM-IC-LABEL: @test_vaddhn_high_s64( +// LLVM-IC-SAME: <2 x i32> {{.*}}[[R:%.*]], <2 x i64> {{.*}}[[A:%.*]], <2 x i64> {{.*}}[[B:%.*]]) +// CIR-LABEL: @vaddhn_high_s64( +int32x4_t test_vaddhn_high_s64(int32x2_t r, int64x2_t a, int64x2_t b) { + // CIR: cir.call @vaddhn_s64( + // CIR: cir.call @vcombine_s32( + + // LLVM-IC: [[ADD:%.*]] = add <2 x i64> [[A]], [[B]] + // LLVM-IC: [[SH:%.*]] = lshr <2 x i64> [[ADD]], splat (i64 32) + // LLVM-IC: [[TR:%.*]] = trunc nuw <2 x i64> [[SH]] to <2 x i32> + // LLVM-IC: [[RES:%.*]] = shufflevector <2 x i32> [[R]], <2 x i32> [[TR]], <4 x i32> <i32 0, i32 1, i32 2, i32 3> + // LLVM-IC: ret <4 x i32> [[RES]] + return vaddhn_high_s64(r, a, b); +} + +// LLVM-IC-LABEL: @test_vaddhn_high_u16( +// LLVM-IC-SAME: <8 x i8> {{.*}}[[R:%.*]], <8 x i16> {{.*}}[[A:%.*]], <8 x i16> {{.*}}[[B:%.*]]) +// CIR-LABEL: @vaddhn_high_u16( +uint8x16_t test_vaddhn_high_u16(uint8x8_t r, uint16x8_t a, uint16x8_t b) { + // CIR: cir.call @vaddhn_u16( + // CIR: cir.call @vcombine_u8( + + // LLVM-IC: [[ADD:%.*]] = add <8 x i16> [[A]], [[B]] + // LLVM-IC: [[SH:%.*]] = lshr <8 x i16> [[ADD]], splat (i16 8) + // LLVM-IC: [[TR:%.*]] = trunc nuw <8 x i16> [[SH]] to <8 x i8> + // LLVM-IC: [[RES:%.*]] = shufflevector <8 x i8> [[R]], <8 x i8> [[TR]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15> + // LLVM-IC: ret <16 x i8> [[RES]] + return vaddhn_high_u16(r, a, b); +} + +// LLVM-IC-LABEL: @test_vaddhn_high_u32( +// LLVM-IC-SAME: <4 x i16> {{.*}}[[R:%.*]], <4 x i32> {{.*}}[[A:%.*]], <4 x i32> {{.*}}[[B:%.*]]) +// CIR-LABEL: @vaddhn_high_u32( +uint16x8_t test_vaddhn_high_u32(uint16x4_t r, uint32x4_t a, uint32x4_t b) { + // CIR: cir.call @vaddhn_u32( + // CIR: cir.call @vcombine_u16( + + // LLVM-IC: [[ADD:%.*]] = add <4 x i32> [[A]], [[B]] + // LLVM-IC: [[SH:%.*]] = lshr <4 x i32> [[ADD]], splat (i32 16) + // LLVM-IC: [[TR:%.*]] = trunc nuw <4 x i32> [[SH]] to <4 x i16> + // LLVM-IC: [[RES:%.*]] = shufflevector <4 x i16> [[R]], <4 x i16> [[TR]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> + // LLVM-IC: ret <8 x i16> [[RES]] + return vaddhn_high_u32(r, a, b); +} + +// LLVM-IC-LABEL: @test_vaddhn_high_u64( +// LLVM-IC-SAME: <2 x i32> {{.*}}[[R:%.*]], <2 x i64> {{.*}}[[A:%.*]], <2 x i64> {{.*}}[[B:%.*]]) +// CIR-LABEL: @vaddhn_high_u64( +uint32x4_t test_vaddhn_high_u64(uint32x2_t r, uint64x2_t a, uint64x2_t b) { + // CIR: cir.call @vaddhn_u64( + // CIR: cir.call @vcombine_u32( + + // LLVM-IC: [[ADD:%.*]] = add <2 x i64> [[A]], [[B]] + // LLVM-IC: [[SH:%.*]] = lshr <2 x i64> [[ADD]], splat (i64 32) + // LLVM-IC: [[TR:%.*]] = trunc nuw <2 x i64> [[SH]] to <2 x i32> + // LLVM-IC: [[RES:%.*]] = shufflevector <2 x i32> [[R]], <2 x i32> [[TR]], <4 x i32> <i32 0, i32 1, i32 2, i32 3> + // LLVM-IC: ret <4 x i32> [[RES]] + return vaddhn_high_u64(r, a, b); +} + +// LLVM-IC-LABEL: @test_vraddhn_s16( +// LLVM-IC-SAME: <8 x i16> {{.*}}[[A:%.*]], <8 x i16> {{.*}}[[B:%.*]]) +// CIR-LABEL: @vraddhn_s16( +int8x8_t test_vraddhn_s16(int16x8_t a, int16x8_t b) { + // CIR: cir.call_llvm_intrinsic "aarch64.neon.raddhn" + + // LLVM-IC: [[RES:%.*]] = call <8 x i8> @llvm.aarch64.neon.raddhn.v8i8(<8 x i16> [[A]], <8 x i16> [[B]]) + // LLVM-IC: ret <8 x i8> [[RES]] + return vraddhn_s16(a, b); +} + +// LLVM-IC-LABEL: @test_vraddhn_s32( +// LLVM-IC-SAME: <4 x i32> {{.*}}[[A:%.*]], <4 x i32> {{.*}}[[B:%.*]]) +// CIR-LABEL: @vraddhn_s32( +int16x4_t test_vraddhn_s32(int32x4_t a, int32x4_t b) { + // CIR: cir.call_llvm_intrinsic "aarch64.neon.raddhn" + + // LLVM-IC: [[RES:%.*]] = call <4 x i16> @llvm.aarch64.neon.raddhn.v4i16(<4 x i32> [[A]], <4 x i32> [[B]]) + // LLVM-IC: ret <4 x i16> [[RES]] + return vraddhn_s32(a, b); +} + +// LLVM-IC-LABEL: @test_vraddhn_s64( +// LLVM-IC-SAME: <2 x i64> {{.*}}[[A:%.*]], <2 x i64> {{.*}}[[B:%.*]]) +// CIR-LABEL: @vraddhn_s64( +int32x2_t test_vraddhn_s64(int64x2_t a, int64x2_t b) { + // CIR: cir.call_llvm_intrinsic "aarch64.neon.raddhn" + + // LLVM-IC: [[RES:%.*]] = call <2 x i32> @llvm.aarch64.neon.raddhn.v2i32(<2 x i64> [[A]], <2 x i64> [[B]]) + // LLVM-IC: ret <2 x i32> [[RES]] + return vraddhn_s64(a, b); +} + +// LLVM-IC-LABEL: @test_vraddhn_u16( +// LLVM-IC-SAME: <8 x i16> {{.*}}[[A:%.*]], <8 x i16> {{.*}}[[B:%.*]]) +// CIR-LABEL: @vraddhn_u16( +uint8x8_t test_vraddhn_u16(uint16x8_t a, uint16x8_t b) { + // CIR: cir.call_llvm_intrinsic "aarch64.neon.raddhn" + + // LLVM-IC: [[RES:%.*]] = call <8 x i8> @llvm.aarch64.neon.raddhn.v8i8(<8 x i16> [[A]], <8 x i16> [[B]]) + // LLVM-IC: ret <8 x i8> [[RES]] + return vraddhn_u16(a, b); +} + +// LLVM-IC-LABEL: @test_vraddhn_u32( +// LLVM-IC-SAME: <4 x i32> {{.*}}[[A:%.*]], <4 x i32> {{.*}}[[B:%.*]]) +// CIR-LABEL: @vraddhn_u32( +uint16x4_t test_vraddhn_u32(uint32x4_t a, uint32x4_t b) { + // CIR: cir.call_llvm_intrinsic "aarch64.neon.raddhn" + + // LLVM-IC: [[RES:%.*]] = call <4 x i16> @llvm.aarch64.neon.raddhn.v4i16(<4 x i32> [[A]], <4 x i32> [[B]]) + // LLVM-IC: ret <4 x i16> [[RES]] + return vraddhn_u32(a, b); +} + +// LLVM-IC-LABEL: @test_vraddhn_u64( +// LLVM-IC-SAME: <2 x i64> {{.*}}[[A:%.*]], <2 x i64> {{.*}}[[B:%.*]]) +// CIR-LABEL: @vraddhn_u64( +uint32x2_t test_vraddhn_u64(uint64x2_t a, uint64x2_t b) { + // CIR: cir.call_llvm_intrinsic "aarch64.neon.raddhn" + + // LLVM-IC: [[RES:%.*]] = call <2 x i32> @llvm.aarch64.neon.raddhn.v2i32(<2 x i64> [[A]], <2 x i64> [[B]]) + // LLVM-IC: ret <2 x i32> [[RES]] + return vraddhn_u64(a, b); +} + +// LLVM-IC-LABEL: @test_vraddhn_high_s16( +// LLVM-IC-SAME: <8 x i8> {{.*}}[[R:%.*]], <8 x i16> {{.*}}[[A:%.*]], <8 x i16> {{.*}}[[B:%.*]]) +// CIR-LABEL: @vraddhn_high_s16( +int8x16_t test_vraddhn_high_s16(int8x8_t r, int16x8_t a, int16x8_t b) { + // CIR: cir.call @vraddhn_s16( + // CIR: cir.call @vcombine_s8( + + // LLVM-IC: [[TMP:%.*]] = call <8 x i8> @llvm.aarch64.neon.raddhn.v8i8(<8 x i16> [[A]], <8 x i16> [[B]]) + // LLVM-IC: [[RES:%.*]] = shufflevector <8 x i8> [[R]], <8 x i8> [[TMP]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15> + // LLVM-IC: ret <16 x i8> [[RES]] + return vraddhn_high_s16(r, a, b); +} + +// LLVM-IC-LABEL: @test_vraddhn_high_s32( +// LLVM-IC-SAME: <4 x i16> {{.*}}[[R:%.*]], <4 x i32> {{.*}}[[A:%.*]], <4 x i32> {{.*}}[[B:%.*]]) +// CIR-LABEL: @vraddhn_high_s32( +int16x8_t test_vraddhn_high_s32(int16x4_t r, int32x4_t a, int32x4_t b) { + // CIR: cir.call @vraddhn_s32( + // CIR: cir.call @vcombine_s16( + + // LLVM-IC: [[TMP:%.*]] = call <4 x i16> @llvm.aarch64.neon.raddhn.v4i16(<4 x i32> [[A]], <4 x i32> [[B]]) + // LLVM-IC: [[RES:%.*]] = shufflevector <4 x i16> [[R]], <4 x i16> [[TMP]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> + // LLVM-IC: ret <8 x i16> [[RES]] + return vraddhn_high_s32(r, a, b); +} + +// LLVM-IC-LABEL: @test_vraddhn_high_s64( +// LLVM-IC-SAME: <2 x i32> {{.*}}[[R:%.*]], <2 x i64> {{.*}}[[A:%.*]], <2 x i64> {{.*}}[[B:%.*]]) +// CIR-LABEL: @vraddhn_high_s64( +int32x4_t test_vraddhn_high_s64(int32x2_t r, int64x2_t a, int64x2_t b) { + // CIR: cir.call @vraddhn_s64( + // CIR: cir.call @vcombine_s32( + + // LLVM-IC: [[TMP:%.*]] = call <2 x i32> @llvm.aarch64.neon.raddhn.v2i32(<2 x i64> [[A]], <2 x i64> [[B]]) + // LLVM-IC: [[RES:%.*]] = shufflevector <2 x i32> [[R]], <2 x i32> [[TMP]], <4 x i32> <i32 0, i32 1, i32 2, i32 3> + // LLVM-IC: ret <4 x i32> [[RES]] + return vraddhn_high_s64(r, a, b); +} + +// LLVM-IC-LABEL: @test_vraddhn_high_u16( +// LLVM-IC-SAME: <8 x i8> {{.*}}[[R:%.*]], <8 x i16> {{.*}}[[A:%.*]], <8 x i16> {{.*}}[[B:%.*]]) +// CIR-LABEL: @vraddhn_high_u16( +uint8x16_t test_vraddhn_high_u16(uint8x8_t r, uint16x8_t a, uint16x8_t b) { + // CIR: cir.call @vraddhn_u16( + // CIR: cir.call @vcombine_u8( + + // LLVM-IC: [[TMP:%.*]] = call <8 x i8> @llvm.aarch64.neon.raddhn.v8i8(<8 x i16> [[A]], <8 x i16> [[B]]) + // LLVM-IC: [[RES:%.*]] = shufflevector <8 x i8> [[R]], <8 x i8> [[TMP]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15> + // LLVM-IC: ret <16 x i8> [[RES]] + return vraddhn_high_u16(r, a, b); +} + +// LLVM-IC-LABEL: @test_vraddhn_high_u32( +// LLVM-IC-SAME: <4 x i16> {{.*}}[[R:%.*]], <4 x i32> {{.*}}[[A:%.*]], <4 x i32> {{.*}}[[B:%.*]]) +// CIR-LABEL: @vraddhn_high_u32( +uint16x8_t test_vraddhn_high_u32(uint16x4_t r, uint32x4_t a, uint32x4_t b) { + // CIR: cir.call @vraddhn_u32( + // CIR: cir.call @vcombine_u16( + + // LLVM-IC: [[TMP:%.*]] = call <4 x i16> @llvm.aarch64.neon.raddhn.v4i16(<4 x i32> [[A]], <4 x i32> [[B]]) + // LLVM-IC: [[RES:%.*]] = shufflevector <4 x i16> [[R]], <4 x i16> [[TMP]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> + // LLVM-IC: ret <8 x i16> [[RES]] + return vraddhn_high_u32(r, a, b); +} + +// LLVM-IC-LABEL: @test_vraddhn_high_u64( +// LLVM-IC-SAME: <2 x i32> {{.*}}[[R:%.*]], <2 x i64> {{.*}}[[A:%.*]], <2 x i64> {{.*}}[[B:%.*]]) +// CIR-LABEL: @vraddhn_high_u64( +uint32x4_t test_vraddhn_high_u64(uint32x2_t r, uint64x2_t a, uint64x2_t b) { + // CIR: cir.call @vraddhn_u64( + // CIR: cir.call @vcombine_u32( + + // LLVM-IC: [[TMP:%.*]] = call <2 x i32> @llvm.aarch64.neon.raddhn.v2i32(<2 x i64> [[A]], <2 x i64> [[B]]) + // LLVM-IC: [[RES:%.*]] = shufflevector <2 x i32> [[R]], <2 x i32> [[TMP]], <4 x i32> <i32 0, i32 1, i32 2, i32 3> + // LLVM-IC: ret <4 x i32> [[RES]] + return vraddhn_high_u64(r, a, b); +} >From d1f738b9cbea688d12c83d9608086909c60fa629 Mon Sep 17 00:00:00 2001 From: Vicky Nguyen <[email protected]> Date: Wed, 24 Jun 2026 19:50:48 -0700 Subject: [PATCH 2/2] [CIR][AArch64] Merge NEON binary intrinsic cases via WidenArgs --- .../include/clang/Basic/AArch64CodeGenUtils.h | 14 ++++--- .../lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp | 40 +++++++++++-------- 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/clang/include/clang/Basic/AArch64CodeGenUtils.h b/clang/include/clang/Basic/AArch64CodeGenUtils.h index d6a4df66ad232..d690f6d9f4d6b 100644 --- a/clang/include/clang/Basic/AArch64CodeGenUtils.h +++ b/clang/include/clang/Basic/AArch64CodeGenUtils.h @@ -41,12 +41,16 @@ enum { Use64BitVectors = (1 << 7), Use128BitVectors = (1 << 8), + // Source operands are double-element-width of the result (e.g. vraddhn). + // ClangIR-only; classic code-gen derives this from the intrinsic's .td. + WidenArgs = (1 << 9), + Vectorize1ArgType = Add1ArgType | VectorizeArgTypes, VectorRet = AddRetType | VectorizeRetType, - VectorRetGetArgs01 = - AddRetType | Add2ArgTypes | VectorizeRetType | VectorizeArgTypes, - FpCmpzModifiers = - AddRetType | VectorizeRetType | Add1ArgType | InventFloatType + VectorRetGetArgs01 = AddRetType | Add2ArgTypes | VectorizeRetType | + VectorizeArgTypes, + FpCmpzModifiers = AddRetType | VectorizeRetType | Add1ArgType | + InventFloatType }; /// Describes an ARM or AArch64 NEON intrinsic, or an AArch64 SISD intrinsic. @@ -312,7 +316,7 @@ const inline ARMNeonVectorIntrinsicInfo AArch64SIMDIntrinsicMap [] = { NEONMAP1(vqshluq_n_v, aarch64_neon_sqshlu, 0), NEONMAP2(vqsub_v, aarch64_neon_uqsub, aarch64_neon_sqsub, Add1ArgType | UnsignedAlts), NEONMAP2(vqsubq_v, aarch64_neon_uqsub, aarch64_neon_sqsub, Add1ArgType | UnsignedAlts), - NEONMAP1(vraddhn_v, aarch64_neon_raddhn, Add1ArgType), + NEONMAP1(vraddhn_v, aarch64_neon_raddhn, Add1ArgType | WidenArgs), NEONMAP1(vrax1q_u64, aarch64_crypto_rax1, 0), NEONMAP2(vrecpe_v, aarch64_neon_frecpe, aarch64_neon_urecpe, 0), NEONMAP2(vrecpeq_v, aarch64_neon_frecpe, aarch64_neon_urecpe, 0), diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp index c5c7cba910ea3..9d08f40b0f5ac 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp @@ -318,6 +318,19 @@ deriveNeonSISDIntrinsicOperandTypes(CIRGenFunction &cgf, unsigned modifier, return {funcResTy, std::move(argTypes)}; } +// Derive the source-operand vector type for a common NEON binary intrinsic. +// The `WidenArgs` modifier marks the narrowing-add family (e.g. raddhn), whose +// operands are the double-element-width form of the result vector `vTy`; +// without it the operands share `vTy`. +static cir::VectorType deriveNeonBinaryArgType(CIRGenBuilderTy &builder, + unsigned modifier, + cir::VectorType vTy) { + if (modifier & WidenArgs) + return builder.getExtendedOrTruncatedElementVectorType(vTy, + /*isExtended=*/true); + return vTy; +} + static mlir::Value emitCommonNeonSISDBuiltinExpr( CIRGenFunction &cgf, const ARMNeonVectorIntrinsicInfo &info, llvm::SmallVectorImpl<mlir::Value> &ops, const CallExpr *expr) { @@ -1088,28 +1101,21 @@ static mlir::Value emitCommonNeonBuiltinExpr( case NEON::BI__builtin_neon_vrhadd_v: case NEON::BI__builtin_neon_vrhaddq_v: case NEON::BI__builtin_neon_vshl_v: - case NEON::BI__builtin_neon_vshlq_v: { + case NEON::BI__builtin_neon_vshlq_v: + case NEON::BI__builtin_neon_vraddhn_v: { + // Pick the signed/unsigned intrinsic when the builtin has both + // (UnsignedAlts); otherwise there is a single intrinsic. + unsigned intrinsic = + ((modifier & UnsignedAlts) && !usgn) ? altLLVMIntrinsic : llvmIntrinsic; llvm::StringRef llvmIntrName = - getLLVMIntrNameNoPrefix(static_cast<llvm::Intrinsic::ID>( - usgn ? llvmIntrinsic : altLLVMIntrinsic)); + getLLVMIntrNameNoPrefix(static_cast<llvm::Intrinsic::ID>(intrinsic)); - mlir::Value result = - emitNeonCall(cgf.getCIRGenModule(), cgf.getBuilder(), - /*argTypes=*/{vTy, vTy}, ops, llvmIntrName, - /*funcResTy=*/vTy, loc); - mlir::Type resultType = cgf.convertType(expr->getType()); - return cgf.getBuilder().createBitcast(result, resultType); - } - case NEON::BI__builtin_neon_vraddhn_v: { - cir::VectorType srcTy = - cgf.getBuilder().getExtendedOrTruncatedElementVectorType( - vTy, /*isExtended=*/true); + cir::VectorType argTy = + deriveNeonBinaryArgType(cgf.getBuilder(), modifier, vTy); - llvm::StringRef llvmIntrName = getLLVMIntrNameNoPrefix( - static_cast<llvm::Intrinsic::ID>(llvmIntrinsic)); mlir::Value result = emitNeonCall(cgf.getCIRGenModule(), cgf.getBuilder(), - /*argTypes=*/{srcTy, srcTy}, ops, llvmIntrName, + /*argTypes=*/{argTy, argTy}, ops, llvmIntrName, /*funcResTy=*/vTy, loc); mlir::Type resultType = cgf.convertType(expr->getType()); return cgf.getBuilder().createBitcast(result, resultType); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
