Skip to content

Commit 32b786c

Browse files
labrineatru
authored andcommitted
[clang][FMV][AArch64] Improve streaming mode compatibility.
* Allow arm-streaming if all the functions versions adhere to it. * Allow arm-streaming-compatible if all the functions versions adhere to it. * Allow arm-locally-streaming regardless of the other functions versions. When the caller needs to toggle the streaming mode all the function versions of the callee must adhere to the same mode, otherwise the call will yield a runtime error. Imagine the versions of the callee live in separate TUs. The version that is visible to the caller will determine the calling convention used when generating code for the callsite. Therefore we cannot support mixing streaming with non-streaming function versions. Imagine TU1 has a streaming caller and calls foo._sme which is streaming-compatible. The codegen for the callsite will not switch off the streaming mode. Then in TU2 we have a version which is non-streaming and could potentially be called in streaming mode. Similarly if the caller is non-streaming and the called version is streaming-compatible the codegen for the callsite will not switch on the streaming mode, but other versions may be streaming.
1 parent 7f1cd78 commit 32b786c

File tree

6 files changed

+173
-55
lines changed

6 files changed

+173
-55
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3811,8 +3811,6 @@ def warn_sme_locally_streaming_has_vl_args_returns : Warning<
38113811
InGroup<AArch64SMEAttributes>, DefaultIgnore;
38123812
def err_conflicting_attributes_arm_state : Error<
38133813
"conflicting attributes for state '%0'">;
3814-
def err_sme_streaming_cannot_be_multiversioned : Error<
3815-
"streaming function cannot be multi-versioned">;
38163814
def err_unknown_arm_state : Error<
38173815
"unknown state '%0'">;
38183816
def err_missing_arm_state : Error<

clang/lib/Sema/SemaDecl.cpp

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11014,6 +11014,9 @@ static bool AttrCompatibleWithMultiVersion(attr::Kind Kind,
1101411014
switch (Kind) {
1101511015
default:
1101611016
return false;
11017+
case attr::ArmLocallyStreaming:
11018+
return MVKind == MultiVersionKind::TargetVersion ||
11019+
MVKind == MultiVersionKind::TargetClones;
1101711020
case attr::Used:
1101811021
return MVKind == MultiVersionKind::Target;
1101911022
case attr::NonNull:
@@ -11150,7 +11153,21 @@ bool Sema::areMultiversionVariantFunctionsCompatible(
1115011153
FunctionType::ExtInfo OldTypeInfo = OldType->getExtInfo();
1115111154
FunctionType::ExtInfo NewTypeInfo = NewType->getExtInfo();
1115211155

11153-
if (OldTypeInfo.getCC() != NewTypeInfo.getCC())
11156+
const auto *OldFPT = OldFD->getType()->getAs<FunctionProtoType>();
11157+
const auto *NewFPT = NewFD->getType()->getAs<FunctionProtoType>();
11158+
11159+
bool ArmStreamingCCMismatched = false;
11160+
if (OldFPT && NewFPT) {
11161+
unsigned Diff =
11162+
OldFPT->getAArch64SMEAttributes() ^ NewFPT->getAArch64SMEAttributes();
11163+
// Arm-streaming, arm-streaming-compatible and non-streaming versions
11164+
// cannot be mixed.
11165+
if (Diff & (FunctionType::SME_PStateSMEnabledMask |
11166+
FunctionType::SME_PStateSMCompatibleMask))
11167+
ArmStreamingCCMismatched = true;
11168+
}
11169+
11170+
if (OldTypeInfo.getCC() != NewTypeInfo.getCC() || ArmStreamingCCMismatched)
1115411171
return Diag(DiffDiagIDAt.first, DiffDiagIDAt.second) << CallingConv;
1115511172

1115611173
QualType OldReturnType = OldType->getReturnType();
@@ -11170,9 +11187,8 @@ bool Sema::areMultiversionVariantFunctionsCompatible(
1117011187
if (!CLinkageMayDiffer && OldFD->isExternC() != NewFD->isExternC())
1117111188
return Diag(DiffDiagIDAt.first, DiffDiagIDAt.second) << LanguageLinkage;
1117211189

11173-
if (CheckEquivalentExceptionSpec(
11174-
OldFD->getType()->getAs<FunctionProtoType>(), OldFD->getLocation(),
11175-
NewFD->getType()->getAs<FunctionProtoType>(), NewFD->getLocation()))
11190+
if (CheckEquivalentExceptionSpec(OldFPT, OldFD->getLocation(), NewFPT,
11191+
NewFD->getLocation()))
1117611192
return true;
1117711193
}
1117811194
return false;

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3024,9 +3024,6 @@ bool Sema::checkTargetVersionAttr(SourceLocation LiteralLoc, Decl *D,
30243024
return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
30253025
<< Unsupported << None << CurFeature << TargetVersion;
30263026
}
3027-
if (IsArmStreamingFunction(cast<FunctionDecl>(D),
3028-
/*IncludeLocallyStreaming=*/false))
3029-
return Diag(LiteralLoc, diag::err_sme_streaming_cannot_be_multiversioned);
30303027
return false;
30313028
}
30323029

@@ -3123,10 +3120,6 @@ bool Sema::checkTargetClonesAttrString(
31233120
HasNotDefault = true;
31243121
}
31253122
}
3126-
if (IsArmStreamingFunction(cast<FunctionDecl>(D),
3127-
/*IncludeLocallyStreaming=*/false))
3128-
return Diag(LiteralLoc,
3129-
diag::err_sme_streaming_cannot_be_multiversioned);
31303123
} else {
31313124
// Other targets ( currently X86 )
31323125
if (Cur.starts_with("arch=")) {
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -emit-llvm -o - %s | FileCheck %s
2+
3+
4+
// CHECK-LABEL: define {{[^@]+}}@n_callee._Msve
5+
// CHECK-SAME: () #[[ATTR0:[0-9]+]] {
6+
//
7+
// CHECK-LABEL: define {{[^@]+}}@n_callee._Msimd
8+
// CHECK-SAME: () #[[ATTR1:[0-9]+]] {
9+
//
10+
__arm_locally_streaming __attribute__((target_clones("sve", "simd"))) void n_callee(void) {}
11+
// CHECK-LABEL: define {{[^@]+}}@n_callee._Msme2
12+
// CHECK-SAME: () #[[ATTR2:[0-9]+]] {
13+
//
14+
__attribute__((target_version("sme2"))) void n_callee(void) {}
15+
// CHECK-LABEL: define {{[^@]+}}@n_callee.default
16+
// CHECK-SAME: () #[[ATTR3:[0-9]+]] {
17+
//
18+
__attribute__((target_version("default"))) void n_callee(void) {}
19+
20+
21+
// CHECK-LABEL: define {{[^@]+}}@s_callee._Msve
22+
// CHECK-SAME: () #[[ATTR4:[0-9]+]] {
23+
//
24+
// CHECK-LABEL: define {{[^@]+}}@s_callee._Msimd
25+
// CHECK-SAME: () #[[ATTR5:[0-9]+]] {
26+
//
27+
__attribute__((target_clones("sve", "simd"))) void s_callee(void) __arm_streaming {}
28+
// CHECK-LABEL: define {{[^@]+}}@s_callee._Msme2
29+
// CHECK-SAME: () #[[ATTR6:[0-9]+]] {
30+
//
31+
__arm_locally_streaming __attribute__((target_version("sme2"))) void s_callee(void) __arm_streaming {}
32+
// CHECK-LABEL: define {{[^@]+}}@s_callee.default
33+
// CHECK-SAME: () #[[ATTR7:[0-9]+]] {
34+
//
35+
__attribute__((target_version("default"))) void s_callee(void) __arm_streaming {}
36+
37+
38+
// CHECK-LABEL: define {{[^@]+}}@sc_callee._Msve
39+
// CHECK-SAME: () #[[ATTR8:[0-9]+]] {
40+
//
41+
// CHECK-LABEL: define {{[^@]+}}@sc_callee._Msimd
42+
// CHECK-SAME: () #[[ATTR9:[0-9]+]] {
43+
//
44+
__attribute__((target_clones("sve", "simd"))) void sc_callee(void) __arm_streaming_compatible {}
45+
// CHECK-LABEL: define {{[^@]+}}@sc_callee._Msme2
46+
// CHECK-SAME: () #[[ATTR10:[0-9]+]] {
47+
//
48+
__arm_locally_streaming __attribute__((target_version("sme2"))) void sc_callee(void) __arm_streaming_compatible {}
49+
// CHECK-LABEL: define {{[^@]+}}@sc_callee.default
50+
// CHECK-SAME: () #[[ATTR11:[0-9]+]] {
51+
//
52+
__attribute__((target_version("default"))) void sc_callee(void) __arm_streaming_compatible {}
53+
54+
55+
// CHECK-LABEL: define {{[^@]+}}@n_caller
56+
// CHECK-SAME: () #[[ATTR3:[0-9]+]] {
57+
// CHECK: call void @n_callee()
58+
// CHECK: call void @s_callee() #[[ATTR12:[0-9]+]]
59+
// CHECK: call void @sc_callee() #[[ATTR13:[0-9]+]]
60+
//
61+
void n_caller(void) {
62+
n_callee();
63+
s_callee();
64+
sc_callee();
65+
}
66+
67+
68+
// CHECK-LABEL: define {{[^@]+}}@s_caller
69+
// CHECK-SAME: () #[[ATTR7:[0-9]+]] {
70+
// CHECK: call void @n_callee()
71+
// CHECK: call void @s_callee() #[[ATTR12]]
72+
// CHECK: call void @sc_callee() #[[ATTR13]]
73+
//
74+
void s_caller(void) __arm_streaming {
75+
n_callee();
76+
s_callee();
77+
sc_callee();
78+
}
79+
80+
81+
// CHECK-LABEL: define {{[^@]+}}@sc_caller
82+
// CHECK-SAME: () #[[ATTR11:[0-9]+]] {
83+
// CHECK: call void @n_callee()
84+
// CHECK: call void @s_callee() #[[ATTR12]]
85+
// CHECK: call void @sc_callee() #[[ATTR13]]
86+
//
87+
void sc_caller(void) __arm_streaming_compatible {
88+
n_callee();
89+
s_callee();
90+
sc_callee();
91+
}
92+
93+
94+
// CHECK: attributes #[[ATTR0:[0-9]+]] = {{.*}} "aarch64_pstate_sm_body"
95+
// CHECK: attributes #[[ATTR1:[0-9]+]] = {{.*}} "aarch64_pstate_sm_body"
96+
// CHECK: attributes #[[ATTR2:[0-9]+]] = {{.*}}
97+
// CHECK: attributes #[[ATTR3]] = {{.*}}
98+
// CHECK: attributes #[[ATTR4:[0-9]+]] = {{.*}} "aarch64_pstate_sm_enabled"
99+
// CHECK: attributes #[[ATTR5:[0-9]+]] = {{.*}} "aarch64_pstate_sm_enabled"
100+
// CHECK: attributes #[[ATTR6:[0-9]+]] = {{.*}} "aarch64_pstate_sm_body" "aarch64_pstate_sm_enabled"
101+
// CHECK: attributes #[[ATTR7]] = {{.*}} "aarch64_pstate_sm_enabled"
102+
// CHECK: attributes #[[ATTR8:[0-9]+]] = {{.*}} "aarch64_pstate_sm_compatible"
103+
// CHECK: attributes #[[ATTR9:[0-9]+]] = {{.*}} "aarch64_pstate_sm_compatible"
104+
// CHECK: attributes #[[ATTR10]] = {{.*}} "aarch64_pstate_sm_body" "aarch64_pstate_sm_compatible"
105+
// CHECK: attributes #[[ATTR11]] = {{.*}} "aarch64_pstate_sm_compatible"
106+
// CHECK: attributes #[[ATTR12]] = {{.*}} "aarch64_pstate_sm_enabled"
107+
// CHECK: attributes #[[ATTR13]] = {{.*}} "aarch64_pstate_sm_compatible"
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -Waarch64-sme-attributes -fsyntax-only -verify %s
2+
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -Waarch64-sme-attributes -fsyntax-only -verify=expected-cpp -x c++ %s
3+
4+
__attribute__((target_clones("sve", "simd"))) void ok_arm_streaming(void) __arm_streaming {}
5+
__arm_locally_streaming __attribute__((target_version("sme2"))) void ok_arm_streaming(void) __arm_streaming {}
6+
__attribute__((target_version("default"))) void ok_arm_streaming(void) __arm_streaming {}
7+
8+
__attribute__((target_clones("sve", "simd"))) void ok_arm_streaming_compatible(void) __arm_streaming_compatible {}
9+
__arm_locally_streaming __attribute__((target_version("sme2"))) void ok_arm_streaming_compatible(void) __arm_streaming_compatible {}
10+
__attribute__((target_version("default"))) void ok_arm_streaming_compatible(void) __arm_streaming_compatible {}
11+
12+
__arm_locally_streaming __attribute__((target_clones("sve", "simd"))) void ok_no_streaming(void) {}
13+
__attribute__((target_version("sme2"))) void ok_no_streaming(void) {}
14+
__attribute__((target_version("default"))) void ok_no_streaming(void) {}
15+
16+
__attribute__((target_clones("sve", "simd"))) void bad_mixed_streaming(void) {}
17+
// expected-cpp-error@+2 {{multiversioned function declaration has a different calling convention}}
18+
// expected-error@+1 {{multiversioned function declaration has a different calling convention}}
19+
__attribute__((target_version("sme2"))) void bad_mixed_streaming(void) __arm_streaming {}
20+
// expected-cpp-error@+2 {{multiversioned function declaration has a different calling convention}}
21+
// expected-error@+1 {{multiversioned function declaration has a different calling convention}}
22+
__attribute__((target_version("default"))) void bad_mixed_streaming(void) __arm_streaming_compatible {}
23+
// expected-cpp-error@+2 {{multiversioned function declaration has a different calling convention}}
24+
// expected-error@+1 {{multiversioned function declaration has a different calling convention}}
25+
__arm_locally_streaming __attribute__((target_version("dotprod"))) void bad_mixed_streaming(void) __arm_streaming {}
26+
27+
void n_caller(void) {
28+
ok_arm_streaming();
29+
ok_arm_streaming_compatible();
30+
ok_no_streaming();
31+
bad_mixed_streaming();
32+
}
33+
34+
void s_caller(void) __arm_streaming {
35+
ok_arm_streaming();
36+
ok_arm_streaming_compatible();
37+
ok_no_streaming();
38+
bad_mixed_streaming();
39+
}
40+
41+
void sc_caller(void) __arm_streaming_compatible {
42+
ok_arm_streaming();
43+
ok_arm_streaming_compatible();
44+
ok_no_streaming();
45+
bad_mixed_streaming();
46+
}

clang/test/Sema/aarch64-sme-func-attrs.c

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -455,48 +455,6 @@ void unimplemented_spill_fill_za(void (*share_zt0_only)(void) __arm_inout("zt0")
455455
share_zt0_only();
456456
}
457457

458-
// expected-cpp-error@+2 {{streaming function cannot be multi-versioned}}
459-
// expected-error@+1 {{streaming function cannot be multi-versioned}}
460-
__attribute__((target_version("sme2")))
461-
void cannot_work_version(void) __arm_streaming {}
462-
// expected-cpp-error@+5 {{function declared 'void ()' was previously declared 'void () __arm_streaming', which has different SME function attributes}}
463-
// expected-cpp-note@-2 {{previous declaration is here}}
464-
// expected-error@+3 {{function declared 'void (void)' was previously declared 'void (void) __arm_streaming', which has different SME function attributes}}
465-
// expected-note@-4 {{previous declaration is here}}
466-
__attribute__((target_version("default")))
467-
void cannot_work_version(void) {}
468-
469-
470-
// expected-cpp-error@+2 {{streaming function cannot be multi-versioned}}
471-
// expected-error@+1 {{streaming function cannot be multi-versioned}}
472-
__attribute__((target_clones("sme2")))
473-
void cannot_work_clones(void) __arm_streaming {}
474-
475-
476-
__attribute__((target("sme2")))
477-
void just_fine_streaming(void) __arm_streaming {}
478-
__attribute__((target_version("sme2")))
479-
void just_fine(void) { just_fine_streaming(); }
480-
__attribute__((target_version("default")))
481-
void just_fine(void) {}
482-
483-
484-
__arm_locally_streaming
485-
__attribute__((target_version("sme2")))
486-
void incompatible_locally_streaming(void) {}
487-
// expected-error@-1 {{attribute 'target_version' multiversioning cannot be combined with attribute '__arm_locally_streaming'}}
488-
// expected-cpp-error@-2 {{attribute 'target_version' multiversioning cannot be combined with attribute '__arm_locally_streaming'}}
489-
__attribute__((target_version("default")))
490-
void incompatible_locally_streaming(void) {}
491-
492-
493-
void fmv_caller() {
494-
cannot_work_version();
495-
cannot_work_clones();
496-
just_fine();
497-
incompatible_locally_streaming();
498-
}
499-
500458
void sme_streaming_with_vl_arg(__SVInt8_t a) __arm_streaming { }
501459

502460
__SVInt8_t sme_streaming_returns_vl(void) __arm_streaming { __SVInt8_t r; return r; }

0 commit comments

Comments
 (0)