Skip to content

Commit

Permalink
[FMV] Allow target version definitions in any order. (#83887)
Browse files Browse the repository at this point in the history
This patch fixes #71698. It allows defining the default target version
prior to other version definitions without raising semantic errors.
  • Loading branch information
labrinea committed Mar 6, 2024
1 parent 20459dd commit 92529eb
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 37 deletions.
15 changes: 12 additions & 3 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11479,6 +11479,16 @@ static bool CheckTargetCausesMultiVersioning(Sema &S, FunctionDecl *OldFD,
bool &Redeclaration,
NamedDecl *&OldDecl,
LookupResult &Previous) {
assert(!OldFD->isMultiVersion() && "Unexpected MultiVersion");

// The definitions should be allowed in any order. If we have discovered
// a new target version and the preceeding was the default, then add the
// corresponding attribute to it.
if (OldFD->getMultiVersionKind() == MultiVersionKind::None &&
NewFD->getMultiVersionKind() == MultiVersionKind::TargetVersion)
OldFD->addAttr(TargetVersionAttr::CreateImplicit(S.Context, "default",
OldFD->getSourceRange()));

const auto *NewTA = NewFD->getAttr<TargetAttr>();
const auto *NewTVA = NewFD->getAttr<TargetVersionAttr>();
const auto *OldTA = OldFD->getAttr<TargetAttr>();
Expand All @@ -11505,9 +11515,8 @@ static bool CheckTargetCausesMultiVersioning(Sema &S, FunctionDecl *OldFD,
}

// If this is 'default', permit the forward declaration.
if (!OldFD->isMultiVersion() &&
((NewTA && NewTA->isDefaultVersion() && !OldTA) ||
(NewTVA && NewTVA->isDefaultVersion() && !OldTVA))) {
if ((NewTA && NewTA->isDefaultVersion() && !OldTA) ||
(NewTVA && NewTVA->isDefaultVersion() && !OldTVA)) {
Redeclaration = true;
OldDecl = OldFD;
OldFD->setIsMultiVersion();
Expand Down
56 changes: 28 additions & 28 deletions clang/test/CodeGen/attr-target-version.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,16 +94,16 @@ int hoo(void) {
// CHECK: @fmv_one.ifunc = weak_odr alias i32 (), ptr @fmv_one
// CHECK: @fmv_two.ifunc = weak_odr alias i32 (), ptr @fmv_two
// CHECK: @fmv_e.ifunc = weak_odr alias i32 (), ptr @fmv_e
// CHECK: @fmv_c.ifunc = weak_odr alias void (), ptr @fmv_c
// CHECK: @fmv_inline.ifunc = weak_odr alias i32 (), ptr @fmv_inline
// CHECK: @fmv_d.ifunc = internal alias i32 (), ptr @fmv_d
// CHECK: @fmv_c.ifunc = weak_odr alias void (), ptr @fmv_c
// CHECK: @fmv = weak_odr ifunc i32 (), ptr @fmv.resolver
// CHECK: @fmv_one = weak_odr ifunc i32 (), ptr @fmv_one.resolver
// CHECK: @fmv_two = weak_odr ifunc i32 (), ptr @fmv_two.resolver
// CHECK: @fmv_e = weak_odr ifunc i32 (), ptr @fmv_e.resolver
// CHECK: @fmv_c = weak_odr ifunc void (), ptr @fmv_c.resolver
// CHECK: @fmv_inline = weak_odr ifunc i32 (), ptr @fmv_inline.resolver
// CHECK: @fmv_d = internal ifunc i32 (), ptr @fmv_d.resolver
// CHECK: @fmv_c = weak_odr ifunc void (), ptr @fmv_c.resolver
//.
// CHECK: Function Attrs: noinline nounwind optnone
// CHECK-LABEL: define {{[^@]+}}@fmv._MflagmMfp16fmlMrng
Expand Down Expand Up @@ -238,11 +238,18 @@ int hoo(void) {
// CHECK-NEXT: ret i32 111
//
//
// CHECK: Function Attrs: noinline nounwind optnone
// CHECK-LABEL: define {{[^@]+}}@fmv_c._Mssbs
// CHECK-SAME: () #[[ATTR2]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret void
// CHECK-LABEL: define {{[^@]+}}@fmv_c.resolver() comdat {
// CHECK-NEXT: resolver_entry:
// CHECK-NEXT: call void @__init_cpu_features_resolver()
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 281474976710656
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 281474976710656
// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
// CHECK: resolver_return:
// CHECK-NEXT: ret ptr @fmv_c._Mssbs
// CHECK: resolver_else:
// CHECK-NEXT: ret ptr @fmv_c.default
//
//
// CHECK: Function Attrs: noinline nounwind optnone
Expand Down Expand Up @@ -405,20 +412,6 @@ int hoo(void) {
// CHECK-NEXT: ret ptr @fmv_d.default
//
//
// CHECK-LABEL: define {{[^@]+}}@fmv_c.resolver() comdat {
// CHECK-NEXT: resolver_entry:
// CHECK-NEXT: call void @__init_cpu_features_resolver()
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 281474976710656
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 281474976710656
// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]]
// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
// CHECK: resolver_return:
// CHECK-NEXT: ret ptr @fmv_c._Mssbs
// CHECK: resolver_else:
// CHECK-NEXT: ret ptr @fmv_c.default
//
//
// CHECK: Function Attrs: noinline nounwind optnone
// CHECK-LABEL: define {{[^@]+}}@recur
// CHECK-SAME: () #[[ATTR2]] {
Expand Down Expand Up @@ -568,6 +561,20 @@ int hoo(void) {
//
//
// CHECK: Function Attrs: noinline nounwind optnone
// CHECK-LABEL: define {{[^@]+}}@fmv_c.default
// CHECK-SAME: () #[[ATTR2]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret void
//
//
// CHECK: Function Attrs: noinline nounwind optnone
// CHECK-LABEL: define {{[^@]+}}@fmv_c._Mssbs
// CHECK-SAME: () #[[ATTR2]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret void
//
//
// CHECK: Function Attrs: noinline nounwind optnone
// CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mf64mmMpmullMsha1
// CHECK-SAME: () #[[ATTR12:[0-9]+]] {
// CHECK-NEXT: entry:
Expand Down Expand Up @@ -700,13 +707,6 @@ int hoo(void) {
// CHECK-NEXT: ret i32 1
//
//
// CHECK: Function Attrs: noinline nounwind optnone
// CHECK-LABEL: define {{[^@]+}}@fmv_c.default
// CHECK-SAME: () #[[ATTR2]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret void
//
//
// CHECK-NOFMV: Function Attrs: noinline nounwind optnone
// CHECK-NOFMV-LABEL: define {{[^@]+}}@fmv
// CHECK-NOFMV-SAME: () #[[ATTR0:[0-9]+]] {
Expand Down
25 changes: 19 additions & 6 deletions clang/test/Sema/attr-target-version.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,25 @@ void __attribute__((target_version("ssbs+fp16fml"))) two(void) {}
//expected-error@+1 {{'main' cannot be a multiversioned function}}
int __attribute__((target_version("lse"))) main(void) { return 1; }

//expected-note@+1 {{previous definition is here}}
int hoo(void) { return 1; }
//expected-note@-1 {{previous definition is here}}
//expected-warning@+2 {{attribute declaration must precede definition}}
//expected-error@+1 {{redefinition of 'hoo'}}
int __attribute__((target_version("dit"))) hoo(void) { return 2; }
// It is ok for the default version to appear first.
int default_first(void) { return 1; }
int __attribute__((target_version("dit"))) default_first(void) { return 2; }
int __attribute__((target_version("mops"))) default_first(void) { return 3; }

// It is ok if the default version is between other versions.
int __attribute__((target_version("simd"))) default_middle(void) {return 0; }
int __attribute__((target_version("default"))) default_middle(void) { return 1; }
int __attribute__((target_version("aes"))) default_middle(void) { return 2; }

// It is ok for the default version to be the last one.
int __attribute__((target_version("rdm"))) default_last(void) {return 0; }
int __attribute__((target_version("lse+aes"))) default_last(void) { return 1; }
int __attribute__((target_version("default"))) default_last(void) { return 2; }

// It is also ok to forward declare the default.
int __attribute__((target_version("default"))) default_fwd_declare(void);
int __attribute__((target_version("sve"))) default_fwd_declare(void) { return 0; }
int default_fwd_declare(void) { return 1; }

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

0 comments on commit 92529eb

Please sign in to comment.