Skip to content

Commit 92529eb

Browse files
authored
[FMV] Allow target version definitions in any order. (#83887)
This patch fixes #71698. It allows defining the default target version prior to other version definitions without raising semantic errors.
1 parent 20459dd commit 92529eb

File tree

3 files changed

+59
-37
lines changed

3 files changed

+59
-37
lines changed

clang/lib/Sema/SemaDecl.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11479,6 +11479,16 @@ static bool CheckTargetCausesMultiVersioning(Sema &S, FunctionDecl *OldFD,
1147911479
bool &Redeclaration,
1148011480
NamedDecl *&OldDecl,
1148111481
LookupResult &Previous) {
11482+
assert(!OldFD->isMultiVersion() && "Unexpected MultiVersion");
11483+
11484+
// The definitions should be allowed in any order. If we have discovered
11485+
// a new target version and the preceeding was the default, then add the
11486+
// corresponding attribute to it.
11487+
if (OldFD->getMultiVersionKind() == MultiVersionKind::None &&
11488+
NewFD->getMultiVersionKind() == MultiVersionKind::TargetVersion)
11489+
OldFD->addAttr(TargetVersionAttr::CreateImplicit(S.Context, "default",
11490+
OldFD->getSourceRange()));
11491+
1148211492
const auto *NewTA = NewFD->getAttr<TargetAttr>();
1148311493
const auto *NewTVA = NewFD->getAttr<TargetVersionAttr>();
1148411494
const auto *OldTA = OldFD->getAttr<TargetAttr>();
@@ -11505,9 +11515,8 @@ static bool CheckTargetCausesMultiVersioning(Sema &S, FunctionDecl *OldFD,
1150511515
}
1150611516

1150711517
// If this is 'default', permit the forward declaration.
11508-
if (!OldFD->isMultiVersion() &&
11509-
((NewTA && NewTA->isDefaultVersion() && !OldTA) ||
11510-
(NewTVA && NewTVA->isDefaultVersion() && !OldTVA))) {
11518+
if ((NewTA && NewTA->isDefaultVersion() && !OldTA) ||
11519+
(NewTVA && NewTVA->isDefaultVersion() && !OldTVA)) {
1151111520
Redeclaration = true;
1151211521
OldDecl = OldFD;
1151311522
OldFD->setIsMultiVersion();

clang/test/CodeGen/attr-target-version.c

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -94,16 +94,16 @@ int hoo(void) {
9494
// CHECK: @fmv_one.ifunc = weak_odr alias i32 (), ptr @fmv_one
9595
// CHECK: @fmv_two.ifunc = weak_odr alias i32 (), ptr @fmv_two
9696
// CHECK: @fmv_e.ifunc = weak_odr alias i32 (), ptr @fmv_e
97+
// CHECK: @fmv_c.ifunc = weak_odr alias void (), ptr @fmv_c
9798
// CHECK: @fmv_inline.ifunc = weak_odr alias i32 (), ptr @fmv_inline
9899
// CHECK: @fmv_d.ifunc = internal alias i32 (), ptr @fmv_d
99-
// CHECK: @fmv_c.ifunc = weak_odr alias void (), ptr @fmv_c
100100
// CHECK: @fmv = weak_odr ifunc i32 (), ptr @fmv.resolver
101101
// CHECK: @fmv_one = weak_odr ifunc i32 (), ptr @fmv_one.resolver
102102
// CHECK: @fmv_two = weak_odr ifunc i32 (), ptr @fmv_two.resolver
103103
// CHECK: @fmv_e = weak_odr ifunc i32 (), ptr @fmv_e.resolver
104+
// CHECK: @fmv_c = weak_odr ifunc void (), ptr @fmv_c.resolver
104105
// CHECK: @fmv_inline = weak_odr ifunc i32 (), ptr @fmv_inline.resolver
105106
// CHECK: @fmv_d = internal ifunc i32 (), ptr @fmv_d.resolver
106-
// CHECK: @fmv_c = weak_odr ifunc void (), ptr @fmv_c.resolver
107107
//.
108108
// CHECK: Function Attrs: noinline nounwind optnone
109109
// CHECK-LABEL: define {{[^@]+}}@fmv._MflagmMfp16fmlMrng
@@ -238,11 +238,18 @@ int hoo(void) {
238238
// CHECK-NEXT: ret i32 111
239239
//
240240
//
241-
// CHECK: Function Attrs: noinline nounwind optnone
242-
// CHECK-LABEL: define {{[^@]+}}@fmv_c._Mssbs
243-
// CHECK-SAME: () #[[ATTR2]] {
244-
// CHECK-NEXT: entry:
245-
// CHECK-NEXT: ret void
241+
// CHECK-LABEL: define {{[^@]+}}@fmv_c.resolver() comdat {
242+
// CHECK-NEXT: resolver_entry:
243+
// CHECK-NEXT: call void @__init_cpu_features_resolver()
244+
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
245+
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 281474976710656
246+
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 281474976710656
247+
// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
248+
// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
249+
// CHECK: resolver_return:
250+
// CHECK-NEXT: ret ptr @fmv_c._Mssbs
251+
// CHECK: resolver_else:
252+
// CHECK-NEXT: ret ptr @fmv_c.default
246253
//
247254
//
248255
// CHECK: Function Attrs: noinline nounwind optnone
@@ -405,20 +412,6 @@ int hoo(void) {
405412
// CHECK-NEXT: ret ptr @fmv_d.default
406413
//
407414
//
408-
// CHECK-LABEL: define {{[^@]+}}@fmv_c.resolver() comdat {
409-
// CHECK-NEXT: resolver_entry:
410-
// CHECK-NEXT: call void @__init_cpu_features_resolver()
411-
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
412-
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 281474976710656
413-
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 281474976710656
414-
// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
415-
// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
416-
// CHECK: resolver_return:
417-
// CHECK-NEXT: ret ptr @fmv_c._Mssbs
418-
// CHECK: resolver_else:
419-
// CHECK-NEXT: ret ptr @fmv_c.default
420-
//
421-
//
422415
// CHECK: Function Attrs: noinline nounwind optnone
423416
// CHECK-LABEL: define {{[^@]+}}@recur
424417
// CHECK-SAME: () #[[ATTR2]] {
@@ -568,6 +561,20 @@ int hoo(void) {
568561
//
569562
//
570563
// CHECK: Function Attrs: noinline nounwind optnone
564+
// CHECK-LABEL: define {{[^@]+}}@fmv_c.default
565+
// CHECK-SAME: () #[[ATTR2]] {
566+
// CHECK-NEXT: entry:
567+
// CHECK-NEXT: ret void
568+
//
569+
//
570+
// CHECK: Function Attrs: noinline nounwind optnone
571+
// CHECK-LABEL: define {{[^@]+}}@fmv_c._Mssbs
572+
// CHECK-SAME: () #[[ATTR2]] {
573+
// CHECK-NEXT: entry:
574+
// CHECK-NEXT: ret void
575+
//
576+
//
577+
// CHECK: Function Attrs: noinline nounwind optnone
571578
// CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mf64mmMpmullMsha1
572579
// CHECK-SAME: () #[[ATTR12:[0-9]+]] {
573580
// CHECK-NEXT: entry:
@@ -700,13 +707,6 @@ int hoo(void) {
700707
// CHECK-NEXT: ret i32 1
701708
//
702709
//
703-
// CHECK: Function Attrs: noinline nounwind optnone
704-
// CHECK-LABEL: define {{[^@]+}}@fmv_c.default
705-
// CHECK-SAME: () #[[ATTR2]] {
706-
// CHECK-NEXT: entry:
707-
// CHECK-NEXT: ret void
708-
//
709-
//
710710
// CHECK-NOFMV: Function Attrs: noinline nounwind optnone
711711
// CHECK-NOFMV-LABEL: define {{[^@]+}}@fmv
712712
// CHECK-NOFMV-SAME: () #[[ATTR0:[0-9]+]] {

clang/test/Sema/attr-target-version.c

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,25 @@ void __attribute__((target_version("ssbs+fp16fml"))) two(void) {}
4242
//expected-error@+1 {{'main' cannot be a multiversioned function}}
4343
int __attribute__((target_version("lse"))) main(void) { return 1; }
4444

45-
//expected-note@+1 {{previous definition is here}}
46-
int hoo(void) { return 1; }
47-
//expected-note@-1 {{previous definition is here}}
48-
//expected-warning@+2 {{attribute declaration must precede definition}}
49-
//expected-error@+1 {{redefinition of 'hoo'}}
50-
int __attribute__((target_version("dit"))) hoo(void) { return 2; }
45+
// It is ok for the default version to appear first.
46+
int default_first(void) { return 1; }
47+
int __attribute__((target_version("dit"))) default_first(void) { return 2; }
48+
int __attribute__((target_version("mops"))) default_first(void) { return 3; }
49+
50+
// It is ok if the default version is between other versions.
51+
int __attribute__((target_version("simd"))) default_middle(void) {return 0; }
52+
int __attribute__((target_version("default"))) default_middle(void) { return 1; }
53+
int __attribute__((target_version("aes"))) default_middle(void) { return 2; }
54+
55+
// It is ok for the default version to be the last one.
56+
int __attribute__((target_version("rdm"))) default_last(void) {return 0; }
57+
int __attribute__((target_version("lse+aes"))) default_last(void) { return 1; }
58+
int __attribute__((target_version("default"))) default_last(void) { return 2; }
59+
60+
// It is also ok to forward declare the default.
61+
int __attribute__((target_version("default"))) default_fwd_declare(void);
62+
int __attribute__((target_version("sve"))) default_fwd_declare(void) { return 0; }
63+
int default_fwd_declare(void) { return 1; }
5164

5265
//expected-warning@+1 {{unsupported '' in the 'target_version' attribute string; 'target_version' attribute ignored}}
5366
int __attribute__((target_version(""))) unsup1(void) { return 1; }

0 commit comments

Comments
 (0)