Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Dec 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions clang/lib/Headers/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down
15 changes: 14 additions & 1 deletion clang/lib/Sema/SemaType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
134 changes: 134 additions & 0 deletions clang/test/CodeGen/arm-vector_type-params-returns.c
Original file line number Diff line number Diff line change
@@ -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

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've just added a REQUIRES line to this test in effd47e since it was failing in my AMDGPU-only build.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you.
I will fix that!

#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;
}
5 changes: 3 additions & 2 deletions clang/test/Sema/aarch64-sve-intrinsics/acle_sve_target.cpp
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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());
}
}

2 changes: 1 addition & 1 deletion clang/test/Sema/arm-vector-types-support.c
Original file line number Diff line number Diff line change
@@ -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=}}
3 changes: 2 additions & 1 deletion clang/test/SemaCUDA/neon-attrs.cu
Original file line number Diff line number Diff line change
Expand Up @@ -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'}}
51 changes: 40 additions & 11 deletions clang/utils/TableGen/NeonEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,8 @@ class NeonEmitter {
// 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);
Expand Down Expand Up @@ -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";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: is it worth calling this arm_common_vector_types.h (as it doesn't contain poly vector types for example).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess there's a question as to why the poly types have been omitted. We don't need to be that precious about the header containing only the bare minimum types that are needed across NEON and SVE. I've seen circumstances where users have wanted the types but nothing else. I know this is not the goal of this patch but it's a step in that direction.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Omitting the poly types was a suggestion I made to allow including #arm_common_vector_types.h into contexts when NEON is not available, but you still want to use the shared vector types (e.g. for SVE/SME).

Strictly speaking you could use the types for interfaces despite of which feature flags are set, but this seems to have been the chosen approach historically. Given that there is no requirement for these types to be available outside of arm_neon.h, I thought it made sense to only share the common types and preserve existing behaviour for the poly types.


// For now, signedness of polynomial types depends on target
OS << "#ifdef __aarch64__\n";
Expand All @@ -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";
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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!");
}
2 changes: 2 additions & 0 deletions clang/utils/TableGen/SveEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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
6 changes: 6 additions & 0 deletions clang/utils/TableGen/TableGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ enum ActionType {
GenArmNeon,
GenArmFP16,
GenArmBF16,
GenArmVectorType,
GenArmNeonSema,
GenArmNeonTest,
GenArmMveHeader,
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions clang/utils/TableGen/TableGenBackends.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down