Author: Alexandros Lamprineas Date: 2024-03-06T10:42:39Z New Revision: 92529eb4aeb2dbb706aedebc1ed9fc4f8045231a
URL: https://github.com/llvm/llvm-project/commit/92529eb4aeb2dbb706aedebc1ed9fc4f8045231a DIFF: https://github.com/llvm/llvm-project/commit/92529eb4aeb2dbb706aedebc1ed9fc4f8045231a.diff LOG: [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. Added: Modified: clang/lib/Sema/SemaDecl.cpp clang/test/CodeGen/attr-target-version.c clang/test/Sema/attr-target-version.c Removed: ################################################################################ diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 210e2835184a95..6b81ee183cc440 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -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>(); @@ -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(); diff --git a/clang/test/CodeGen/attr-target-version.c b/clang/test/CodeGen/attr-target-version.c index 56a42499d0a7ca..ae1a8772f6cc07 100644 --- a/clang/test/CodeGen/attr-target-version.c +++ b/clang/test/CodeGen/attr-target-version.c @@ -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 @@ -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 @@ -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]] { @@ -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: @@ -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]+]] { diff --git a/clang/test/Sema/attr-target-version.c b/clang/test/Sema/attr-target-version.c index 587c721de5e322..e2940c434c2ff5 100644 --- a/clang/test/Sema/attr-target-version.c +++ b/clang/test/Sema/attr-target-version.c @@ -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; } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits