-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[FMV][AArch64] Emit mangled default version if explicitly specified. #120022
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
Conversation
Curently we need at least one more version other than the default to trigger FMV. However we would like a header file declaration __attribute__((target_version("default"))) void f(void); to guarantee that there will be f.default
@llvm/pr-subscribers-clang-codegen @llvm/pr-subscribers-clang Author: Alexandros Lamprineas (labrinea) ChangesCurently we need at least one more version other than the default to trigger FMV. However we would like a header file declaration attribute((target_version("default"))) void f(void); to guarantee that there will be f.default Patch is 23.72 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/120022.diff 7 Files Affected:
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index d3d5c0743a520b..b65e3dc2496797 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -4280,7 +4280,7 @@ void CodeGenModule::emitMultiVersionFunctions() {
getContext().forEachMultiversionedFunctionVersion(
FD, [&](const FunctionDecl *CurFD) {
llvm::SmallVector<StringRef, 8> Feats;
- bool IsDefined = CurFD->doesThisDeclarationHaveABody();
+ bool IsDefined = CurFD->getDefinition() != nullptr;
if (const auto *TA = CurFD->getAttr<TargetAttr>()) {
assert(getTarget().getTriple().isX86() && "Unsupported target");
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 55e891e3acf20d..7c3e5ceabb771d 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -11073,9 +11073,9 @@ bool Sema::shouldLinkDependentDeclWithPrevious(Decl *D, Decl *PrevDecl) {
static bool CheckMultiVersionValue(Sema &S, const FunctionDecl *FD) {
const auto *TA = FD->getAttr<TargetAttr>();
const auto *TVA = FD->getAttr<TargetVersionAttr>();
- assert(
- (TA || TVA) &&
- "MultiVersion candidate requires a target or target_version attribute");
+
+ assert((TA || TVA) && "Expecting target or target_version attribute");
+
const TargetInfo &TargetInfo = S.Context.getTargetInfo();
enum ErrType { Feature = 0, Architecture = 1 };
@@ -11372,10 +11372,6 @@ static bool CheckMultiVersionFirstFunction(Sema &S, FunctionDecl *FD) {
// otherwise it is treated as a normal function.
if (TA && !TA->isDefaultVersion())
return false;
- // The target_version attribute only causes Multiversioning if this
- // declaration is NOT the default version.
- if (TVA && TVA->isDefaultVersion())
- return false;
if ((TA || TVA) && CheckMultiVersionValue(S, FD)) {
FD->setInvalidDecl();
@@ -11422,26 +11418,24 @@ static bool CheckDeclarationCausesMultiVersioning(Sema &S, FunctionDecl *OldFD,
LookupResult &Previous) {
assert(!OldFD->isMultiVersion() && "Unexpected MultiVersion");
+ const auto *NewTA = NewFD->getAttr<TargetAttr>();
+ const auto *OldTA = OldFD->getAttr<TargetAttr>();
+ const auto *NewTVA = NewFD->getAttr<TargetVersionAttr>();
+ const auto *OldTVA = OldFD->getAttr<TargetVersionAttr>();
+
+ assert((NewTA || NewTVA) && "Excpecting target or target_version attribute");
+
// 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.
patchDefaultTargetVersion(NewFD, OldFD);
- const auto *NewTA = NewFD->getAttr<TargetAttr>();
- const auto *NewTVA = NewFD->getAttr<TargetVersionAttr>();
- const auto *OldTA = OldFD->getAttr<TargetAttr>();
-
// If the old decl is NOT MultiVersioned yet, and we don't cause that
// to change, this is a simple redeclaration.
if (NewTA && !NewTA->isDefaultVersion() &&
(!OldTA || OldTA->getFeaturesStr() == NewTA->getFeaturesStr()))
return false;
- // The target_version attribute only causes Multiversioning if this
- // declaration is NOT the default version.
- if (NewTVA && NewTVA->isDefaultVersion())
- return false;
-
// Otherwise, this decl causes MultiVersioning.
if (CheckMultiVersionAdditionalRules(S, OldFD, NewFD, true,
NewTVA ? MultiVersionKind::TargetVersion
@@ -11456,7 +11450,8 @@ static bool CheckDeclarationCausesMultiVersioning(Sema &S, FunctionDecl *OldFD,
}
// If this is 'default', permit the forward declaration.
- if (NewTA && NewTA->isDefaultVersion() && !OldTA) {
+ if ((NewTA && NewTA->isDefaultVersion() && !OldTA) ||
+ (NewTVA && NewTVA->isDefaultVersion() && !OldTVA)) {
Redeclaration = true;
OldDecl = OldFD;
OldFD->setIsMultiVersion();
@@ -11464,7 +11459,7 @@ static bool CheckDeclarationCausesMultiVersioning(Sema &S, FunctionDecl *OldFD,
return false;
}
- if (CheckMultiVersionValue(S, OldFD)) {
+ if ((OldTA || OldTVA) && CheckMultiVersionValue(S, OldFD)) {
S.Diag(NewFD->getLocation(), diag::note_multiversioning_caused_here);
NewFD->setInvalidDecl();
return true;
@@ -11761,9 +11756,7 @@ static bool CheckMultiVersionAdditionalDecl(
// Else, this is simply a non-redecl case. Checking the 'value' is only
// necessary in the Target case, since The CPUSpecific/Dispatch cases are
// handled in the attribute adding step.
- if ((NewMVKind == MultiVersionKind::TargetVersion ||
- NewMVKind == MultiVersionKind::Target) &&
- CheckMultiVersionValue(S, NewFD)) {
+ if ((NewTA || NewTVA) && CheckMultiVersionValue(S, NewFD)) {
NewFD->setInvalidDecl();
return true;
}
@@ -11799,6 +11792,12 @@ static bool CheckMultiVersionAdditionalDecl(
static bool CheckMultiVersionFunction(Sema &S, FunctionDecl *NewFD,
bool &Redeclaration, NamedDecl *&OldDecl,
LookupResult &Previous) {
+ const TargetInfo &TI = S.getASTContext().getTargetInfo();
+
+ // Abort if FMV is disabled.
+ if (TI.getTriple().isAArch64() && !TI.hasFeature("fmv"))
+ return false;
+
const auto *NewTA = NewFD->getAttr<TargetAttr>();
const auto *NewTVA = NewFD->getAttr<TargetVersionAttr>();
const auto *NewCPUDisp = NewFD->getAttr<CPUDispatchAttr>();
@@ -11821,14 +11820,12 @@ static bool CheckMultiVersionFunction(Sema &S, FunctionDecl *NewFD,
return false;
}
- const llvm::Triple &T = S.getASTContext().getTargetInfo().getTriple();
-
// Target attribute on AArch64 is not used for multiversioning
- if (NewTA && T.isAArch64())
+ if (NewTA && TI.getTriple().isAArch64())
return false;
// Target attribute on RISCV is not used for multiversioning
- if (NewTA && T.isRISCV())
+ if (NewTA && TI.getTriple().isRISCV())
return false;
if (!OldDecl || !OldDecl->getAsFunction() ||
diff --git a/clang/test/CodeGen/AArch64/fmv-mix-explicit-implicit-default.c b/clang/test/CodeGen/AArch64/fmv-mix-explicit-implicit-default.c
new file mode 100644
index 00000000000000..032738fb9664d4
--- /dev/null
+++ b/clang/test/CodeGen/AArch64/fmv-mix-explicit-implicit-default.c
@@ -0,0 +1,221 @@
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature -fmv -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-NOFMV
+
+int implicit_default_decl_first(void);
+__attribute__((target_version("default"))) int implicit_default_decl_first(void) { return 1; }
+int caller1(void) { return implicit_default_decl_first(); }
+
+__attribute__((target_version("default"))) int explicit_default_def_first(void) { return 2; }
+int explicit_default_def_first(void);
+int caller2(void) { return explicit_default_def_first(); }
+
+int implicit_default_def_first(void) { return 3; }
+__attribute__((target_version("default"))) int implicit_default_def_first(void);
+int caller3(void) { return implicit_default_def_first(); }
+
+__attribute__((target_version("default"))) int explicit_default_decl_first(void);
+int explicit_default_decl_first(void) { return 4; }
+int caller4(void) { return explicit_default_decl_first(); }
+
+int no_def_implicit_default_first(void);
+__attribute__((target_version("default"))) int no_def_implicit_default_first(void);
+int caller5(void) { return no_def_implicit_default_first(); }
+
+__attribute__((target_version("default"))) int no_def_explicit_default_first(void);
+int no_def_explicit_default_first(void);
+int caller6(void) { return no_def_explicit_default_first(); }
+//.
+// CHECK: @implicit_default_decl_first = weak_odr ifunc i32 (), ptr @implicit_default_decl_first.resolver
+// CHECK: @explicit_default_def_first = weak_odr ifunc i32 (), ptr @explicit_default_def_first.resolver
+// CHECK: @implicit_default_def_first = weak_odr ifunc i32 (), ptr @implicit_default_def_first.resolver
+// CHECK: @explicit_default_decl_first = weak_odr ifunc i32 (), ptr @explicit_default_decl_first.resolver
+//.
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: define {{[^@]+}}@implicit_default_decl_first.default
+// CHECK-SAME: () #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: ret i32 1
+//
+//
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: define {{[^@]+}}@caller1
+// CHECK-SAME: () #[[ATTR1:[0-9]+]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[CALL:%.*]] = call i32 @implicit_default_decl_first()
+// CHECK-NEXT: ret i32 [[CALL]]
+//
+//
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: define {{[^@]+}}@explicit_default_def_first.default
+// CHECK-SAME: () #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: ret i32 2
+//
+//
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: define {{[^@]+}}@caller2
+// CHECK-SAME: () #[[ATTR1]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[CALL:%.*]] = call i32 @explicit_default_def_first()
+// CHECK-NEXT: ret i32 [[CALL]]
+//
+//
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: define {{[^@]+}}@implicit_default_def_first.default
+// CHECK-SAME: () #[[ATTR1]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: ret i32 3
+//
+//
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: define {{[^@]+}}@caller3
+// CHECK-SAME: () #[[ATTR1]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[CALL:%.*]] = call i32 @implicit_default_def_first()
+// CHECK-NEXT: ret i32 [[CALL]]
+//
+//
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: define {{[^@]+}}@explicit_default_decl_first.default
+// CHECK-SAME: () #[[ATTR0]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: ret i32 4
+//
+//
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: define {{[^@]+}}@caller4
+// CHECK-SAME: () #[[ATTR1]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[CALL:%.*]] = call i32 @explicit_default_decl_first()
+// CHECK-NEXT: ret i32 [[CALL]]
+//
+//
+// CHECK: declare i32 @no_def_implicit_default_first() #[[ATTR2:[0-9]+]]
+//
+//
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: define {{[^@]+}}@caller5
+// CHECK-SAME: () #[[ATTR1]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[CALL:%.*]] = call i32 @no_def_implicit_default_first()
+// CHECK-NEXT: ret i32 [[CALL]]
+//
+//
+// CHECK: declare i32 @no_def_explicit_default_first() #[[ATTR2]]
+//
+//
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: define {{[^@]+}}@caller6
+// CHECK-SAME: () #[[ATTR1]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[CALL:%.*]] = call i32 @no_def_explicit_default_first()
+// CHECK-NEXT: ret i32 [[CALL]]
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@implicit_default_decl_first.resolver() comdat {
+// CHECK-NEXT: resolver_entry:
+// CHECK-NEXT: ret ptr @implicit_default_decl_first.default
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@explicit_default_def_first.resolver() comdat {
+// CHECK-NEXT: resolver_entry:
+// CHECK-NEXT: ret ptr @explicit_default_def_first.default
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@implicit_default_def_first.resolver() comdat {
+// CHECK-NEXT: resolver_entry:
+// CHECK-NEXT: ret ptr @implicit_default_def_first.default
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@explicit_default_decl_first.resolver() comdat {
+// CHECK-NEXT: resolver_entry:
+// CHECK-NEXT: ret ptr @explicit_default_decl_first.default
+//
+//
+// CHECK: declare i32 @no_def_implicit_default_first.default() #[[ATTR2]]
+//
+//
+// CHECK: declare i32 @no_def_explicit_default_first.default() #[[ATTR2]]
+//
+//
+// CHECK-NOFMV: Function Attrs: noinline nounwind optnone
+// CHECK-NOFMV-LABEL: define {{[^@]+}}@caller1
+// CHECK-NOFMV-SAME: () #[[ATTR0:[0-9]+]] {
+// CHECK-NOFMV-NEXT: entry:
+// CHECK-NOFMV-NEXT: [[CALL:%.*]] = call i32 @implicit_default_decl_first()
+// CHECK-NOFMV-NEXT: ret i32 [[CALL]]
+//
+//
+// CHECK-NOFMV: Function Attrs: noinline nounwind optnone
+// CHECK-NOFMV-LABEL: define {{[^@]+}}@implicit_default_decl_first
+// CHECK-NOFMV-SAME: () #[[ATTR1:[0-9]+]] {
+// CHECK-NOFMV-NEXT: entry:
+// CHECK-NOFMV-NEXT: ret i32 1
+//
+//
+// CHECK-NOFMV: Function Attrs: noinline nounwind optnone
+// CHECK-NOFMV-LABEL: define {{[^@]+}}@caller2
+// CHECK-NOFMV-SAME: () #[[ATTR0]] {
+// CHECK-NOFMV-NEXT: entry:
+// CHECK-NOFMV-NEXT: [[CALL:%.*]] = call i32 @explicit_default_def_first()
+// CHECK-NOFMV-NEXT: ret i32 [[CALL]]
+//
+//
+// CHECK-NOFMV: Function Attrs: noinline nounwind optnone
+// CHECK-NOFMV-LABEL: define {{[^@]+}}@explicit_default_def_first
+// CHECK-NOFMV-SAME: () #[[ATTR1]] {
+// CHECK-NOFMV-NEXT: entry:
+// CHECK-NOFMV-NEXT: ret i32 2
+//
+//
+// CHECK-NOFMV: Function Attrs: noinline nounwind optnone
+// CHECK-NOFMV-LABEL: define {{[^@]+}}@implicit_default_def_first
+// CHECK-NOFMV-SAME: () #[[ATTR0]] {
+// CHECK-NOFMV-NEXT: entry:
+// CHECK-NOFMV-NEXT: ret i32 3
+//
+//
+// CHECK-NOFMV: Function Attrs: noinline nounwind optnone
+// CHECK-NOFMV-LABEL: define {{[^@]+}}@caller3
+// CHECK-NOFMV-SAME: () #[[ATTR0]] {
+// CHECK-NOFMV-NEXT: entry:
+// CHECK-NOFMV-NEXT: [[CALL:%.*]] = call i32 @implicit_default_def_first()
+// CHECK-NOFMV-NEXT: ret i32 [[CALL]]
+//
+//
+// CHECK-NOFMV: Function Attrs: noinline nounwind optnone
+// CHECK-NOFMV-LABEL: define {{[^@]+}}@caller4
+// CHECK-NOFMV-SAME: () #[[ATTR0]] {
+// CHECK-NOFMV-NEXT: entry:
+// CHECK-NOFMV-NEXT: [[CALL:%.*]] = call i32 @explicit_default_decl_first()
+// CHECK-NOFMV-NEXT: ret i32 [[CALL]]
+//
+//
+// CHECK-NOFMV: Function Attrs: noinline nounwind optnone
+// CHECK-NOFMV-LABEL: define {{[^@]+}}@explicit_default_decl_first
+// CHECK-NOFMV-SAME: () #[[ATTR1]] {
+// CHECK-NOFMV-NEXT: entry:
+// CHECK-NOFMV-NEXT: ret i32 4
+//
+//
+// CHECK-NOFMV: Function Attrs: noinline nounwind optnone
+// CHECK-NOFMV-LABEL: define {{[^@]+}}@caller5
+// CHECK-NOFMV-SAME: () #[[ATTR0]] {
+// CHECK-NOFMV-NEXT: entry:
+// CHECK-NOFMV-NEXT: [[CALL:%.*]] = call i32 @no_def_implicit_default_first()
+// CHECK-NOFMV-NEXT: ret i32 [[CALL]]
+//
+//
+// CHECK-NOFMV: declare i32 @no_def_implicit_default_first() #[[ATTR2:[0-9]+]]
+//
+//
+// CHECK-NOFMV: Function Attrs: noinline nounwind optnone
+// CHECK-NOFMV-LABEL: define {{[^@]+}}@caller6
+// CHECK-NOFMV-SAME: () #[[ATTR0]] {
+// CHECK-NOFMV-NEXT: entry:
+// CHECK-NOFMV-NEXT: [[CALL:%.*]] = call i32 @no_def_explicit_default_first()
+// CHECK-NOFMV-NEXT: ret i32 [[CALL]]
+//
+//
+// CHECK-NOFMV: declare i32 @no_def_explicit_default_first() #[[ATTR2]]
+//.
diff --git a/clang/test/CodeGen/attr-target-version.c b/clang/test/CodeGen/attr-target-version.c
index 428e7937d8d39e..951401c498deb8 100644
--- a/clang/test/CodeGen/attr-target-version.c
+++ b/clang/test/CodeGen/attr-target-version.c
@@ -143,10 +143,12 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
// CHECK: @fmv_d = internal ifunc i32 (), ptr @fmv_d.resolver
// CHECK: @fmv_c = weak_odr ifunc void (), ptr @fmv_c.resolver
// CHECK: @fmv_inline = weak_odr ifunc i32 (), ptr @fmv_inline.resolver
+// CHECK: @reca = weak_odr ifunc void (), ptr @reca.resolver
// CHECK: @unused_with_default_def = weak_odr ifunc i32 (), ptr @unused_with_default_def.resolver
// CHECK: @unused_with_implicit_default_def = weak_odr ifunc i32 (), ptr @unused_with_implicit_default_def.resolver
// CHECK: @unused_with_implicit_forward_default_def = weak_odr ifunc i32 (), ptr @unused_with_implicit_forward_default_def.resolver
// CHECK: @default_def_with_version_decls = weak_odr ifunc i32 (), ptr @default_def_with_version_decls.resolver
+// CHECK: @recb = weak_odr ifunc void (), ptr @recb.resolver
//.
// CHECK: Function Attrs: noinline nounwind optnone
// CHECK-LABEL: define {{[^@]+}}@fmv._MflagmMfp16fmlMrng
@@ -287,8 +289,15 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
//
//
// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: define {{[^@]+}}@fmv_default.default
+// CHECK-SAME: () #[[ATTR9]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: ret i32 111
+//
+//
+// CHECK: Function Attrs: noinline nounwind optnone
// CHECK-LABEL: define {{[^@]+}}@fmv_c._Mssbs
-// CHECK-SAME: () #[[ATTR16:[0-9]+]] {
+// CHECK-SAME: () #[[ATTR17:[0-9]+]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: ret void
//
@@ -313,13 +322,6 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
//
//
// CHECK: Function Attrs: noinline nounwind optnone
-// CHECK-LABEL: define {{[^@]+}}@fmv_default
-// CHECK-SAME: () #[[ATTR9]] {
-// CHECK-NEXT: entry:
-// CHECK-NEXT: ret i32 111
-//
-//
-// CHECK: Function Attrs: noinline nounwind optnone
// CHECK-LABEL: define {{[^@]+}}@recur
// CHECK-SAME: () #[[ATTR15]] {
// CHECK-NEXT: entry:
@@ -895,6 +897,19 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
// CHECK-NEXT: ret ptr @fmv_inline.default
//
//
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: define {{[^@]+}}@reca.default
+// CHECK-SAME: () #[[ATTR9]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: call void @recb()
+// CHECK-NEXT: ret void
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@reca.resolver() comdat {
+// CHECK-NEXT: resolver_entry:
+// CHECK-NEXT: ret ptr @reca.default
+//
+//
// CHECK-LABEL: define {{[^@]+}}@unused_with_default_def.resolver() comdat {
// CHECK-NEXT: resolver_entry:
// CHECK-NEXT: call void @__init_cpu_features_resolver()
@@ -959,6 +974,26 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
// CHECK-NEXT: ret ptr @default_def_with_version_decls.default
//
//
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: define {{[^@]+}}@recb.default
+// CHECK-SAME: () #[[ATTR9]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: call void @func()
+// CHECK-NEXT: ret void
+//
+//
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: define {{[^@]+}}@func
+// CHECK-SAME: () #[[ATTR15]] {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: ret void
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@recb.resolver() comdat {
+// CHECK-NEXT: resolver_entry:
+// CHECK-NEXT: ret ptr @recb.default
+//
+//
// CHECK-NOFMV: Function Attrs: noinline nounwind optnone
// CHECK-NOFMV-LABEL: define {{[^@]+}}@foo
// CHECK-NOFMV-SAME: () #[[ATTR0:[0-9]+]] {
diff --git a/clang/test/CodeGenCXX/fmv-namespace.cpp b/clang/test/CodeGenCXX/fmv-namespace.cpp
index 1a76ee03565245..75f29e1c779759 100644
--- a/clang/test/CodeGenCXX/fmv-namespace.cpp
+++ b/clang/test/CodeGenCXX/fmv-namespace.cpp
@@ -28,34 +28,40 @@ __attribute((target_version("mops"))) int bar() { return 1; }
// CHECK: @_ZN4Name3fooEv = weak_odr ifunc i32 (), ptr @_ZN4Name3fooEv.resolver
// CHECK: @_ZN3Foo3barEv = weak_odr ifunc i32 (), ptr @_ZN3Foo3barEv.resolver
//.
-// CHECK-LABEL: define dso_local noundef i32 @_ZN4Name3fooEv._Msve(
+// CHECK-LABEL: define dso_local noundef i32 @_ZN4Name3fooEv.default(
// CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: ret i32 0
+//
+//
+// CHECK-LABEL: define dso_local noundef i32 @_ZN4Name3fooEv._Msve(
+// CHECK-SAME: ) #[[ATTR1:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: ret i32 1
//
//
// CHECK-LABEL: define dso_local noundef i32 @_Z3barv(
-// CHECK-SAME: ) #[[ATTR1:[0-9]+]] {
+// CHECK-SAME: ) #[[ATTR2:[0-9]+]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[CALL:%.*]] = call noundef i32 @_ZN4Name3fooEv()
// CHECK-NEXT: ret i32 [[CALL]]
//
//
// CHECK-LABEL: define dso_local noundef i32 @_ZN9OtherName3fooEv._Msve(
-// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK-SAME: ) #[[ATTR1]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: ret i32 2
//
//
// CHECK-LABEL: define dso_local noundef i32 @_Z3bazv(
-// CHECK-SAME: ) #[[ATTR1]] {
+// CHECK-SAME: ) #[[ATTR2]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[CALL:%.*]] = call noundef i32 @_ZN9OtherName3fooEv()
// CHECK-NEXT: ret i32 [[CALL]]
//
//
// CHECK-LABEL: define dso_local noundef i32 @_ZN3Foo3barEv.default(
-// CHECK-SAME: ) #[[ATTR3:[0-9]+]] {
+// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: ret i32 0
//
@@ -66,12 +72,6 @@ __attribute((target_version("mops"))) int bar() { return 1; }
// CHECK-NEXT: ret ...
[truncated]
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just left a NIT.
Co-authored-by: Daniel Kiss <[email protected]>
Thanks! |
Currently we need at least one more version other than the default to trigger FMV. However we would like a header file declaration
attribute((target_version("default"))) void f(void);
to guarantee that there will be f.default