Skip to content

[clang][FMV][AArch64] Improve streaming mode compatibility. #100181

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 5 commits into from
Jul 26, 2024
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
2 changes: 0 additions & 2 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -3802,8 +3802,6 @@ def warn_sme_locally_streaming_has_vl_args_returns : Warning<
InGroup<AArch64SMEAttributes>, DefaultIgnore;
def err_conflicting_attributes_arm_state : Error<
"conflicting attributes for state '%0'">;
def err_sme_streaming_cannot_be_multiversioned : Error<
"streaming function cannot be multi-versioned">;
def err_unknown_arm_state : Error<
"unknown state '%0'">;
def err_missing_arm_state : Error<
Expand Down
24 changes: 20 additions & 4 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11009,6 +11009,9 @@ static bool AttrCompatibleWithMultiVersion(attr::Kind Kind,
switch (Kind) {
default:
return false;
case attr::ArmLocallyStreaming:
return MVKind == MultiVersionKind::TargetVersion ||
MVKind == MultiVersionKind::TargetClones;
case attr::Used:
return MVKind == MultiVersionKind::Target;
case attr::NonNull:
Expand Down Expand Up @@ -11145,7 +11148,21 @@ bool Sema::areMultiversionVariantFunctionsCompatible(
FunctionType::ExtInfo OldTypeInfo = OldType->getExtInfo();
FunctionType::ExtInfo NewTypeInfo = NewType->getExtInfo();

if (OldTypeInfo.getCC() != NewTypeInfo.getCC())
const auto *OldFPT = OldFD->getType()->getAs<FunctionProtoType>();
const auto *NewFPT = NewFD->getType()->getAs<FunctionProtoType>();

bool ArmStreamingCCMismatched = false;
if (OldFPT && NewFPT) {
unsigned Diff =
OldFPT->getAArch64SMEAttributes() ^ NewFPT->getAArch64SMEAttributes();
// Arm-streaming, arm-streaming-compatible and non-streaming versions
// cannot be mixed.
if (Diff & (FunctionType::SME_PStateSMEnabledMask |
FunctionType::SME_PStateSMCompatibleMask))
ArmStreamingCCMismatched = true;
}

if (OldTypeInfo.getCC() != NewTypeInfo.getCC() || ArmStreamingCCMismatched)
return Diag(DiffDiagIDAt.first, DiffDiagIDAt.second) << CallingConv;

QualType OldReturnType = OldType->getReturnType();
Expand All @@ -11165,9 +11182,8 @@ bool Sema::areMultiversionVariantFunctionsCompatible(
if (!CLinkageMayDiffer && OldFD->isExternC() != NewFD->isExternC())
return Diag(DiffDiagIDAt.first, DiffDiagIDAt.second) << LanguageLinkage;

if (CheckEquivalentExceptionSpec(
OldFD->getType()->getAs<FunctionProtoType>(), OldFD->getLocation(),
NewFD->getType()->getAs<FunctionProtoType>(), NewFD->getLocation()))
if (CheckEquivalentExceptionSpec(OldFPT, OldFD->getLocation(), NewFPT,
NewFD->getLocation()))
return true;
}
return false;
Expand Down
7 changes: 0 additions & 7 deletions clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3024,9 +3024,6 @@ bool Sema::checkTargetVersionAttr(SourceLocation LiteralLoc, Decl *D,
return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
<< Unsupported << None << CurFeature << TargetVersion;
}
if (IsArmStreamingFunction(cast<FunctionDecl>(D),
/*IncludeLocallyStreaming=*/false))
return Diag(LiteralLoc, diag::err_sme_streaming_cannot_be_multiversioned);
return false;
}

Expand Down Expand Up @@ -3123,10 +3120,6 @@ bool Sema::checkTargetClonesAttrString(
HasNotDefault = true;
}
}
if (IsArmStreamingFunction(cast<FunctionDecl>(D),
/*IncludeLocallyStreaming=*/false))
return Diag(LiteralLoc,
diag::err_sme_streaming_cannot_be_multiversioned);
} else {
// Other targets ( currently X86 )
if (Cur.starts_with("arch=")) {
Expand Down
107 changes: 107 additions & 0 deletions clang/test/CodeGen/aarch64-fmv-streaming.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -emit-llvm -o - %s | FileCheck %s


// CHECK-LABEL: define {{[^@]+}}@n_callee._Msve
// CHECK-SAME: () #[[ATTR0:[0-9]+]] {
//
// CHECK-LABEL: define {{[^@]+}}@n_callee._Msimd
// CHECK-SAME: () #[[ATTR1:[0-9]+]] {
//
__arm_locally_streaming __attribute__((target_clones("sve", "simd"))) void n_callee(void) {}
// CHECK-LABEL: define {{[^@]+}}@n_callee._Msme2
// CHECK-SAME: () #[[ATTR2:[0-9]+]] {
//
__attribute__((target_version("sme2"))) void n_callee(void) {}
// CHECK-LABEL: define {{[^@]+}}@n_callee.default
// CHECK-SAME: () #[[ATTR3:[0-9]+]] {
//
__attribute__((target_version("default"))) void n_callee(void) {}


// CHECK-LABEL: define {{[^@]+}}@s_callee._Msve
// CHECK-SAME: () #[[ATTR4:[0-9]+]] {
//
// CHECK-LABEL: define {{[^@]+}}@s_callee._Msimd
// CHECK-SAME: () #[[ATTR5:[0-9]+]] {
//
__attribute__((target_clones("sve", "simd"))) void s_callee(void) __arm_streaming {}
// CHECK-LABEL: define {{[^@]+}}@s_callee._Msme2
// CHECK-SAME: () #[[ATTR6:[0-9]+]] {
//
__arm_locally_streaming __attribute__((target_version("sme2"))) void s_callee(void) __arm_streaming {}
// CHECK-LABEL: define {{[^@]+}}@s_callee.default
// CHECK-SAME: () #[[ATTR7:[0-9]+]] {
//
__attribute__((target_version("default"))) void s_callee(void) __arm_streaming {}


// CHECK-LABEL: define {{[^@]+}}@sc_callee._Msve
// CHECK-SAME: () #[[ATTR8:[0-9]+]] {
//
// CHECK-LABEL: define {{[^@]+}}@sc_callee._Msimd
// CHECK-SAME: () #[[ATTR9:[0-9]+]] {
//
__attribute__((target_clones("sve", "simd"))) void sc_callee(void) __arm_streaming_compatible {}
// CHECK-LABEL: define {{[^@]+}}@sc_callee._Msme2
// CHECK-SAME: () #[[ATTR10:[0-9]+]] {
//
__arm_locally_streaming __attribute__((target_version("sme2"))) void sc_callee(void) __arm_streaming_compatible {}
// CHECK-LABEL: define {{[^@]+}}@sc_callee.default
// CHECK-SAME: () #[[ATTR11:[0-9]+]] {
//
__attribute__((target_version("default"))) void sc_callee(void) __arm_streaming_compatible {}


// CHECK-LABEL: define {{[^@]+}}@n_caller
// CHECK-SAME: () #[[ATTR3:[0-9]+]] {
// CHECK: call void @n_callee()
// CHECK: call void @s_callee() #[[ATTR12:[0-9]+]]
// CHECK: call void @sc_callee() #[[ATTR13:[0-9]+]]
//
void n_caller(void) {
n_callee();
s_callee();
sc_callee();
}


// CHECK-LABEL: define {{[^@]+}}@s_caller
// CHECK-SAME: () #[[ATTR7:[0-9]+]] {
// CHECK: call void @n_callee()
// CHECK: call void @s_callee() #[[ATTR12]]
// CHECK: call void @sc_callee() #[[ATTR13]]
//
void s_caller(void) __arm_streaming {
n_callee();
s_callee();
sc_callee();
}


// CHECK-LABEL: define {{[^@]+}}@sc_caller
// CHECK-SAME: () #[[ATTR11:[0-9]+]] {
// CHECK: call void @n_callee()
// CHECK: call void @s_callee() #[[ATTR12]]
// CHECK: call void @sc_callee() #[[ATTR13]]
//
void sc_caller(void) __arm_streaming_compatible {
n_callee();
s_callee();
sc_callee();
}


// CHECK: attributes #[[ATTR0:[0-9]+]] = {{.*}} "aarch64_pstate_sm_body"
// CHECK: attributes #[[ATTR1:[0-9]+]] = {{.*}} "aarch64_pstate_sm_body"
// CHECK: attributes #[[ATTR2:[0-9]+]] = {{.*}}
// CHECK: attributes #[[ATTR3]] = {{.*}}
// CHECK: attributes #[[ATTR4:[0-9]+]] = {{.*}} "aarch64_pstate_sm_enabled"
// CHECK: attributes #[[ATTR5:[0-9]+]] = {{.*}} "aarch64_pstate_sm_enabled"
// CHECK: attributes #[[ATTR6:[0-9]+]] = {{.*}} "aarch64_pstate_sm_body" "aarch64_pstate_sm_enabled"
// CHECK: attributes #[[ATTR7]] = {{.*}} "aarch64_pstate_sm_enabled"
// CHECK: attributes #[[ATTR8:[0-9]+]] = {{.*}} "aarch64_pstate_sm_compatible"
// CHECK: attributes #[[ATTR9:[0-9]+]] = {{.*}} "aarch64_pstate_sm_compatible"
// CHECK: attributes #[[ATTR10]] = {{.*}} "aarch64_pstate_sm_body" "aarch64_pstate_sm_compatible"
// CHECK: attributes #[[ATTR11]] = {{.*}} "aarch64_pstate_sm_compatible"
// CHECK: attributes #[[ATTR12]] = {{.*}} "aarch64_pstate_sm_enabled"
// CHECK: attributes #[[ATTR13]] = {{.*}} "aarch64_pstate_sm_compatible"
46 changes: 46 additions & 0 deletions clang/test/Sema/aarch64-fmv-streaming.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -Waarch64-sme-attributes -fsyntax-only -verify %s
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -Waarch64-sme-attributes -fsyntax-only -verify=expected-cpp -x c++ %s

__attribute__((target_clones("sve", "simd"))) void ok_arm_streaming(void) __arm_streaming {}
__arm_locally_streaming __attribute__((target_version("sme2"))) void ok_arm_streaming(void) __arm_streaming {}
__attribute__((target_version("default"))) void ok_arm_streaming(void) __arm_streaming {}

__attribute__((target_clones("sve", "simd"))) void ok_arm_streaming_compatible(void) __arm_streaming_compatible {}
__arm_locally_streaming __attribute__((target_version("sme2"))) void ok_arm_streaming_compatible(void) __arm_streaming_compatible {}
__attribute__((target_version("default"))) void ok_arm_streaming_compatible(void) __arm_streaming_compatible {}

__arm_locally_streaming __attribute__((target_clones("sve", "simd"))) void ok_no_streaming(void) {}
__attribute__((target_version("sme2"))) void ok_no_streaming(void) {}
__attribute__((target_version("default"))) void ok_no_streaming(void) {}

__attribute__((target_clones("sve", "simd"))) void bad_mixed_streaming(void) {}
// expected-cpp-error@+2 {{multiversioned function declaration has a different calling convention}}
// expected-error@+1 {{multiversioned function declaration has a different calling convention}}
__attribute__((target_version("sme2"))) void bad_mixed_streaming(void) __arm_streaming {}
// expected-cpp-error@+2 {{multiversioned function declaration has a different calling convention}}
// expected-error@+1 {{multiversioned function declaration has a different calling convention}}
__attribute__((target_version("default"))) void bad_mixed_streaming(void) __arm_streaming_compatible {}
// expected-cpp-error@+2 {{multiversioned function declaration has a different calling convention}}
// expected-error@+1 {{multiversioned function declaration has a different calling convention}}
__arm_locally_streaming __attribute__((target_version("dotprod"))) void bad_mixed_streaming(void) __arm_streaming {}

void n_caller(void) {
ok_arm_streaming();
ok_arm_streaming_compatible();
ok_no_streaming();
bad_mixed_streaming();
}

void s_caller(void) __arm_streaming {
ok_arm_streaming();
ok_arm_streaming_compatible();
ok_no_streaming();
bad_mixed_streaming();
}

void sc_caller(void) __arm_streaming_compatible {
ok_arm_streaming();
ok_arm_streaming_compatible();
ok_no_streaming();
bad_mixed_streaming();
}
42 changes: 0 additions & 42 deletions clang/test/Sema/aarch64-sme-func-attrs.c
Original file line number Diff line number Diff line change
Expand Up @@ -455,48 +455,6 @@ void unimplemented_spill_fill_za(void (*share_zt0_only)(void) __arm_inout("zt0")
share_zt0_only();
}

// expected-cpp-error@+2 {{streaming function cannot be multi-versioned}}
// expected-error@+1 {{streaming function cannot be multi-versioned}}
__attribute__((target_version("sme2")))
void cannot_work_version(void) __arm_streaming {}
// expected-cpp-error@+5 {{function declared 'void ()' was previously declared 'void () __arm_streaming', which has different SME function attributes}}
// expected-cpp-note@-2 {{previous declaration is here}}
// expected-error@+3 {{function declared 'void (void)' was previously declared 'void (void) __arm_streaming', which has different SME function attributes}}
// expected-note@-4 {{previous declaration is here}}
__attribute__((target_version("default")))
void cannot_work_version(void) {}


// expected-cpp-error@+2 {{streaming function cannot be multi-versioned}}
// expected-error@+1 {{streaming function cannot be multi-versioned}}
__attribute__((target_clones("sme2")))
void cannot_work_clones(void) __arm_streaming {}


__attribute__((target("sme2")))
void just_fine_streaming(void) __arm_streaming {}
__attribute__((target_version("sme2")))
void just_fine(void) { just_fine_streaming(); }
__attribute__((target_version("default")))
void just_fine(void) {}


__arm_locally_streaming
__attribute__((target_version("sme2")))
void incompatible_locally_streaming(void) {}
// expected-error@-1 {{attribute 'target_version' multiversioning cannot be combined with attribute '__arm_locally_streaming'}}
// expected-cpp-error@-2 {{attribute 'target_version' multiversioning cannot be combined with attribute '__arm_locally_streaming'}}
__attribute__((target_version("default")))
void incompatible_locally_streaming(void) {}


void fmv_caller() {
cannot_work_version();
cannot_work_clones();
just_fine();
incompatible_locally_streaming();
}

void sme_streaming_with_vl_arg(__SVInt8_t a) __arm_streaming { }

__SVInt8_t sme_streaming_returns_vl(void) __arm_streaming { __SVInt8_t r; return r; }
Expand Down
Loading