[Clang][AArch64] Add fix vector types to header into SVE (#73258)

This patch is needed for the reduction instructions in sve2.1
 It add a new header to sve with all the fixed vector types.
  The new types are only added if neon is not declared.
This commit is contained in:
CarolineConcatto
2023-12-13 08:59:41 +00:00
committed by GitHub
parent 41aa0d4690
commit ed2d497291
10 changed files with 206 additions and 16 deletions

View File

@@ -387,6 +387,8 @@ if(ARM IN_LIST LLVM_TARGETS_TO_BUILD OR AArch64 IN_LIST LLVM_TARGETS_TO_BUILD)
clang_generate_header(-gen-arm-mve-header arm_mve.td arm_mve.h)
# Generate arm_cde.h
clang_generate_header(-gen-arm-cde-header arm_cde.td arm_cde.h)
# Generate arm_vector_types.h
clang_generate_header(-gen-arm-vector-type arm_neon.td arm_vector_types.h)
# Add headers to target specific lists
list(APPEND arm_common_generated_files
@@ -403,6 +405,7 @@ if(ARM IN_LIST LLVM_TARGETS_TO_BUILD OR AArch64 IN_LIST LLVM_TARGETS_TO_BUILD)
"${CMAKE_CURRENT_BINARY_DIR}/arm_sve.h"
"${CMAKE_CURRENT_BINARY_DIR}/arm_sme_draft_spec_subject_to_change.h"
"${CMAKE_CURRENT_BINARY_DIR}/arm_bf16.h"
"${CMAKE_CURRENT_BINARY_DIR}/arm_vector_types.h"
)
endif()
if(RISCV IN_LIST LLVM_TARGETS_TO_BUILD)

View File

@@ -8360,12 +8360,25 @@ static void HandleNeonVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr,
// not to need a separate attribute)
if (!(S.Context.getTargetInfo().hasFeature("neon") ||
S.Context.getTargetInfo().hasFeature("mve") ||
IsTargetCUDAAndHostARM)) {
S.Context.getTargetInfo().hasFeature("sve") ||
S.Context.getTargetInfo().hasFeature("sme") ||
IsTargetCUDAAndHostARM) &&
VecKind == VectorKind::Neon) {
S.Diag(Attr.getLoc(), diag::err_attribute_unsupported)
<< Attr << "'neon', 'mve', 'sve' or 'sme'";
Attr.setInvalid();
return;
}
if (!(S.Context.getTargetInfo().hasFeature("neon") ||
S.Context.getTargetInfo().hasFeature("mve") ||
IsTargetCUDAAndHostARM) &&
VecKind == VectorKind::NeonPoly) {
S.Diag(Attr.getLoc(), diag::err_attribute_unsupported)
<< Attr << "'neon' or 'mve'";
Attr.setInvalid();
return;
}
// Check the attribute arguments.
if (Attr.getNumArgs() != 1) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)

View File

@@ -0,0 +1,134 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 3
// RUN: %clang_cc1 -DSVE_HEADER -triple aarch64 -target-feature +sve -emit-llvm -O2 -o - %s | opt -S -passes=mem2reg,sroa | FileCheck %s
// RUN: %clang_cc1 -DSVE_HEADER -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -o - /dev/null %s
// RUN: %clang_cc1 -DNEON_HEADER -triple aarch64 -target-feature +sve -emit-llvm -O2 -o - %s | opt -S -passes=mem2reg,sroa | FileCheck %s
// RUN: %clang_cc1 -DNEON_HEADER -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -o - /dev/null %s
// RUN: %clang_cc1 -DSVE_HEADER -DNEON_HEADER -triple aarch64 -target-feature +sve -emit-llvm -O2 -o - %s | opt -S -passes=mem2reg,sroa | FileCheck %s
// RUN: %clang_cc1 -DSVE_HEADER -DNEON_HEADER -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -o - /dev/null %s
// RUN: %clang_cc1 -DNEON_HEADER -DSVE_HEADER2 -triple aarch64 -target-feature +sve -emit-llvm -O2 -o - %s | opt -S -passes=mem2reg,sroa | FileCheck %s
// RUN: %clang_cc1 -DNEON_HEADER -DSVE_HEADER2 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -S -disable-O0-optnone -Werror -Wall -o - /dev/null %s
#ifdef SVE_HEADER
#include <arm_sve.h>
#endif
#ifdef NEON_HEADER
#include <arm_neon.h>
#endif
#ifdef SVE_HEADER_2
#include <arm_sve.h>
#endif
// function return types
// CHECK-LABEL: define dso_local <8 x half> @test_ret_v8f16(
// CHECK-SAME: <8 x half> noundef returned [[V:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret <8 x half> [[V]]
//
float16x8_t test_ret_v8f16(float16x8_t v) {
return v;
}
// CHECK-LABEL: define dso_local <4 x float> @test_ret_v4f32(
// CHECK-SAME: <4 x float> noundef returned [[V:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret <4 x float> [[V]]
//
float32x4_t test_ret_v4f32(float32x4_t v) {
return v;
}
// CHECK-LABEL: define dso_local <2 x double> @test_ret_v2f64(
// CHECK-SAME: <2 x double> noundef returned [[V:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret <2 x double> [[V]]
//
float64x2_t test_ret_v2f64(float64x2_t v) {
return v;
}
// CHECK-LABEL: define dso_local <8 x bfloat> @test_ret_v8bf16(
// CHECK-SAME: <8 x bfloat> noundef returned [[V:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret <8 x bfloat> [[V]]
//
bfloat16x8_t test_ret_v8bf16(bfloat16x8_t v) {
return v;
}
// CHECK-LABEL: define dso_local <16 x i8> @test_ret_v16s8(
// CHECK-SAME: <16 x i8> noundef returned [[V:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret <16 x i8> [[V]]
//
int8x16_t test_ret_v16s8(int8x16_t v) {
return v;
}
// CHECK-LABEL: define dso_local <8 x i16> @test_ret_v8s16(
// CHECK-SAME: <8 x i16> noundef returned [[V:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret <8 x i16> [[V]]
//
int16x8_t test_ret_v8s16(int16x8_t v) {
return v;
}
// CHECK-LABEL: define dso_local <4 x i32> @test_ret_v32s4(
// CHECK-SAME: <4 x i32> noundef returned [[V:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret <4 x i32> [[V]]
//
int32x4_t test_ret_v32s4(int32x4_t v) {
return v;
}
// CHECK-LABEL: define dso_local <2 x i64> @test_ret_v64s2(
// CHECK-SAME: <2 x i64> noundef returned [[V:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret <2 x i64> [[V]]
//
int64x2_t test_ret_v64s2(int64x2_t v) {
return v;
}
// CHECK-LABEL: define dso_local <16 x i8> @test_ret_v16u8(
// CHECK-SAME: <16 x i8> noundef returned [[V:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret <16 x i8> [[V]]
//
uint8x16_t test_ret_v16u8(uint8x16_t v) {
return v;
}
// CHECK-LABEL: define dso_local <8 x i16> @test_ret_v8u16(
// CHECK-SAME: <8 x i16> noundef returned [[V:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret <8 x i16> [[V]]
//
uint16x8_t test_ret_v8u16(uint16x8_t v) {
return v;
}
// CHECK-LABEL: define dso_local <4 x i32> @test_ret_v32u4(
// CHECK-SAME: <4 x i32> noundef returned [[V:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret <4 x i32> [[V]]
//
uint32x4_t test_ret_v32u4(uint32x4_t v) {
return v;
}
// CHECK-LABEL: define dso_local <2 x i64> @test_ret_v64u2(
// CHECK-SAME: <2 x i64> noundef returned [[V:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret <2 x i64> [[V]]
//
uint64x2_t test_ret_v64u2(uint64x2_t v) {
return v;
}

View File

@@ -1,4 +1,4 @@
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -fsyntax-only -verify -emit-llvm -o - -ferror-limit 100 %s
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +neon -fsyntax-only -verify -emit-llvm -o - -ferror-limit 100 %s
// REQUIRES: aarch64-registered-target
// Test that functions with the correct target attributes can use the correct SVE intrinsics.
@@ -29,4 +29,5 @@ void __attribute__((target("sve2-sha3"))) test_sve2_sha3()
void __attribute__((target("sve2"))) test_f16(svbool_t pg)
{
svlogb_f16_z(pg, svundef_f16());
}
}

View File

@@ -1,5 +1,5 @@
// RUN: %clang_cc1 %s -triple armv7 -fsyntax-only -verify
typedef __attribute__((neon_vector_type(2))) int int32x2_t; // expected-error{{'neon_vector_type' attribute is not supported on targets missing 'neon' or 'mve'; specify an appropriate -march= or -mcpu=}}
typedef __attribute__((neon_vector_type(2))) int int32x2_t; // expected-error{{'neon_vector_type' attribute is not supported on targets missing 'neon', 'mve', 'sve' or 'sme'; specify an appropriate -march= or -mcpu=}}
typedef __attribute__((neon_polyvector_type(16))) short poly8x16_t; // expected-error{{'neon_polyvector_type' attribute is not supported on targets missing 'neon' or 'mve'; specify an appropriate -march= or -mcpu=}}
typedef __attribute__((arm_sve_vector_bits(256))) void nosveflag; // expected-error{{'arm_sve_vector_bits' attribute is not supported on targets missing 'sve'; specify an appropriate -march= or -mcpu=}}

View File

@@ -15,7 +15,8 @@
// quiet-no-diagnostics
typedef __attribute__((neon_vector_type(4))) float float32x4_t;
// expected-error@-1 {{'neon_vector_type' attribute is not supported on targets missing 'neon' or 'mve'}}
// expected-error@-1 {{'neon_vector_type' attribute is not supported on targets missing 'neon', 'mve', 'sve' or 'sme'}}
// expect
typedef unsigned char poly8_t;
typedef __attribute__((neon_polyvector_type(8))) poly8_t poly8x8_t;
// expected-error@-1 {{'neon_polyvector_type' attribute is not supported on targets missing 'neon' or 'mve'}}

View File

@@ -593,6 +593,8 @@ public:
// Emit arm_bf16.h.inc
void runBF16(raw_ostream &o);
void runVectorTypes(raw_ostream &o);
// Emit all the __builtin prototypes used in arm_neon.h, arm_fp16.h and
// arm_bf16.h
void runHeader(raw_ostream &o);
@@ -2355,13 +2357,7 @@ void NeonEmitter::run(raw_ostream &OS) {
OS << "#include <arm_bf16.h>\n";
// Emit NEON-specific scalar typedefs.
OS << "typedef float float32_t;\n";
OS << "typedef __fp16 float16_t;\n";
OS << "#ifdef __aarch64__\n";
OS << "typedef double float64_t;\n";
OS << "#endif\n\n";
OS << "#include <arm_vector_types.h>\n";
// For now, signedness of polynomial types depends on target
OS << "#ifdef __aarch64__\n";
@@ -2374,10 +2370,7 @@ void NeonEmitter::run(raw_ostream &OS) {
OS << "typedef int16_t poly16_t;\n";
OS << "typedef int64_t poly64_t;\n";
OS << "#endif\n";
emitNeonTypeDefs("cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfdQdPcQPcPsQPsPlQPl", OS);
emitNeonTypeDefs("bQb", OS);
emitNeonTypeDefs("PcQPcPsQPsPlQPl", OS);
OS << "#define __ai static __inline__ __attribute__((__always_inline__, "
"__nodebug__))\n\n";
@@ -2546,6 +2539,38 @@ void NeonEmitter::runFP16(raw_ostream &OS) {
OS << "#endif /* __ARM_FP16_H */\n";
}
void NeonEmitter::runVectorTypes(raw_ostream &OS) {
OS << "/*===---- arm_vector_types - ARM vector type "
"------===\n"
" *\n"
" *\n"
" * Part of the LLVM Project, under the Apache License v2.0 with LLVM "
"Exceptions.\n"
" * See https://llvm.org/LICENSE.txt for license information.\n"
" * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n"
" *\n"
" *===-----------------------------------------------------------------"
"------===\n"
" */\n\n";
OS << "#if !defined(__ARM_NEON_H) && !defined(__ARM_SVE_H)\n";
OS << "#error \"This file should not be used standalone. Please include"
" arm_neon.h or arm_sve.h instead\"\n\n";
OS << "#endif\n";
OS << "#ifndef __ARM_NEON_TYPES_H\n";
OS << "#define __ARM_NEON_TYPES_H\n";
OS << "typedef float float32_t;\n";
OS << "typedef __fp16 float16_t;\n";
OS << "#ifdef __aarch64__\n";
OS << "typedef double float64_t;\n";
OS << "#endif\n\n";
emitNeonTypeDefs("cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfdQd", OS);
emitNeonTypeDefs("bQb", OS);
OS << "#endif // __ARM_NEON_TYPES_H\n";
}
void NeonEmitter::runBF16(raw_ostream &OS) {
OS << "/*===---- arm_bf16.h - ARM BF16 intrinsics "
"-----------------------------------===\n"
@@ -2640,6 +2665,10 @@ void clang::EmitNeonSema(RecordKeeper &Records, raw_ostream &OS) {
NeonEmitter(Records).runHeader(OS);
}
void clang::EmitVectorTypes(RecordKeeper &Records, raw_ostream &OS) {
NeonEmitter(Records).runVectorTypes(OS);
}
void clang::EmitNeonTest(RecordKeeper &Records, raw_ostream &OS) {
llvm_unreachable("Neon test generation no longer implemented!");
}

View File

@@ -1286,6 +1286,7 @@ void SVEEmitter::createHeader(raw_ostream &OS) {
OS << "typedef __SVBfloat16_t svbfloat16_t;\n";
OS << "#include <arm_bf16.h>\n";
OS << "#include <arm_vector_types.h>\n";
OS << "typedef __SVFloat32_t svfloat32_t;\n";
OS << "typedef __SVFloat64_t svfloat64_t;\n";
@@ -1730,4 +1731,5 @@ void EmitSmeBuiltinCG(RecordKeeper &Records, raw_ostream &OS) {
void EmitSmeRangeChecks(RecordKeeper &Records, raw_ostream &OS) {
SVEEmitter(Records).createSMERangeChecks(OS);
}
} // End namespace clang

View File

@@ -73,6 +73,7 @@ enum ActionType {
GenArmNeon,
GenArmFP16,
GenArmBF16,
GenArmVectorType,
GenArmNeonSema,
GenArmNeonTest,
GenArmMveHeader,
@@ -229,6 +230,8 @@ cl::opt<ActionType> Action(
clEnumValN(GenArmNeon, "gen-arm-neon", "Generate arm_neon.h for clang"),
clEnumValN(GenArmFP16, "gen-arm-fp16", "Generate arm_fp16.h for clang"),
clEnumValN(GenArmBF16, "gen-arm-bf16", "Generate arm_bf16.h for clang"),
clEnumValN(GenArmVectorType, "gen-arm-vector-type",
"Generate arm_vector_types.h for clang"),
clEnumValN(GenArmNeonSema, "gen-arm-neon-sema",
"Generate ARM NEON sema support for clang"),
clEnumValN(GenArmNeonTest, "gen-arm-neon-test",
@@ -449,6 +452,9 @@ bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
case GenArmFP16:
EmitFP16(Records, OS);
break;
case GenArmVectorType:
EmitVectorTypes(Records, OS);
break;
case GenArmBF16:
EmitBF16(Records, OS);
break;

View File

@@ -97,6 +97,7 @@ void EmitNeon(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
void EmitFP16(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
void EmitBF16(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
void EmitNeonSema(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
void EmitVectorTypes(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
void EmitNeonTest(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
void EmitSveHeader(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);