2018-10-26 02:57:19 +08:00
|
|
|
// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=LINUX
|
|
|
|
// RUN: %clang_cc1 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS
|
|
|
|
|
Implement Attribute Target MultiVersioning
GCC's attribute 'target', in addition to being an optimization hint,
also allows function multiversioning. We currently have the former
implemented, this is the latter's implementation.
This works by enabling functions with the same name/signature to coexist,
so that they can all be emitted. Multiversion state is stored in the
FunctionDecl itself, and SemaDecl manages the definitions.
Note that it ends up having to permit redefinition of functions so
that they can all be emitted. Additionally, all versions of the function
must be emitted, so this also manages that.
Note that this includes some additional rules that GCC does not, since
defining something as a MultiVersion function after a usage has been made illegal.
The only 'history rewriting' that happens is if a function is emitted before
it has been converted to a multiversion'ed function, at which point its name
needs to be changed.
Function templates and virtual functions are NOT yet supported (not supported
in GCC either).
Additionally, constructors/destructors are disallowed, but the former is
planned.
llvm-svn: 322028
2018-01-09 05:34:17 +08:00
|
|
|
int __attribute__((target("sse4.2"))) foo(void) { return 0; }
|
|
|
|
int __attribute__((target("arch=sandybridge"))) foo(void);
|
|
|
|
int __attribute__((target("arch=ivybridge"))) foo(void) {return 1;}
|
2020-06-10 06:25:46 +08:00
|
|
|
int __attribute__((target("arch=goldmont"))) foo(void) {return 3;}
|
|
|
|
int __attribute__((target("arch=goldmont-plus"))) foo(void) {return 4;}
|
|
|
|
int __attribute__((target("arch=tremont"))) foo(void) {return 5;}
|
|
|
|
int __attribute__((target("arch=icelake-client"))) foo(void) {return 6;}
|
|
|
|
int __attribute__((target("arch=icelake-server"))) foo(void) {return 7;}
|
2020-06-22 04:24:43 +08:00
|
|
|
int __attribute__((target("arch=cooperlake"))) foo(void) {return 8;}
|
|
|
|
int __attribute__((target("arch=tigerlake"))) foo(void) {return 9;}
|
[X86] Support -march=sapphirerapids
Support -march=sapphirerapids for x86.
Compare with Icelake Server, it includes 14 more new features. They are
amxtile, amxint8, amxbf16, avx512bf16, avx512vp2intersect, cldemote,
enqcmd, movdir64b, movdiri, ptwrite, serialize, shstk, tsxldtrk, waitpkg.
Reviewed By: craig.topper
Differential Revision: https://reviews.llvm.org/D86503
2020-08-25 12:27:02 +08:00
|
|
|
int __attribute__((target("arch=sapphirerapids"))) foo(void) {return 10;}
|
2020-10-25 00:00:33 +08:00
|
|
|
int __attribute__((target("arch=alderlake"))) foo(void) {return 11;}
|
2021-04-13 09:24:34 +08:00
|
|
|
int __attribute__((target("arch=rocketlake"))) foo(void) {return 12;}
|
Implement Attribute Target MultiVersioning
GCC's attribute 'target', in addition to being an optimization hint,
also allows function multiversioning. We currently have the former
implemented, this is the latter's implementation.
This works by enabling functions with the same name/signature to coexist,
so that they can all be emitted. Multiversion state is stored in the
FunctionDecl itself, and SemaDecl manages the definitions.
Note that it ends up having to permit redefinition of functions so
that they can all be emitted. Additionally, all versions of the function
must be emitted, so this also manages that.
Note that this includes some additional rules that GCC does not, since
defining something as a MultiVersion function after a usage has been made illegal.
The only 'history rewriting' that happens is if a function is emitted before
it has been converted to a multiversion'ed function, at which point its name
needs to be changed.
Function templates and virtual functions are NOT yet supported (not supported
in GCC either).
Additionally, constructors/destructors are disallowed, but the former is
planned.
llvm-svn: 322028
2018-01-09 05:34:17 +08:00
|
|
|
int __attribute__((target("default"))) foo(void) { return 2; }
|
|
|
|
|
2022-02-15 22:27:12 +08:00
|
|
|
int bar(void) {
|
Implement Attribute Target MultiVersioning
GCC's attribute 'target', in addition to being an optimization hint,
also allows function multiversioning. We currently have the former
implemented, this is the latter's implementation.
This works by enabling functions with the same name/signature to coexist,
so that they can all be emitted. Multiversion state is stored in the
FunctionDecl itself, and SemaDecl manages the definitions.
Note that it ends up having to permit redefinition of functions so
that they can all be emitted. Additionally, all versions of the function
must be emitted, so this also manages that.
Note that this includes some additional rules that GCC does not, since
defining something as a MultiVersion function after a usage has been made illegal.
The only 'history rewriting' that happens is if a function is emitted before
it has been converted to a multiversion'ed function, at which point its name
needs to be changed.
Function templates and virtual functions are NOT yet supported (not supported
in GCC either).
Additionally, constructors/destructors are disallowed, but the former is
planned.
llvm-svn: 322028
2018-01-09 05:34:17 +08:00
|
|
|
return foo();
|
|
|
|
}
|
|
|
|
|
|
|
|
inline int __attribute__((target("sse4.2"))) foo_inline(void) { return 0; }
|
|
|
|
inline int __attribute__((target("arch=sandybridge"))) foo_inline(void);
|
|
|
|
inline int __attribute__((target("arch=ivybridge"))) foo_inline(void) {return 1;}
|
|
|
|
inline int __attribute__((target("default"))) foo_inline(void) { return 2; }
|
|
|
|
|
2022-02-15 22:27:12 +08:00
|
|
|
int bar2(void) {
|
Implement Attribute Target MultiVersioning
GCC's attribute 'target', in addition to being an optimization hint,
also allows function multiversioning. We currently have the former
implemented, this is the latter's implementation.
This works by enabling functions with the same name/signature to coexist,
so that they can all be emitted. Multiversion state is stored in the
FunctionDecl itself, and SemaDecl manages the definitions.
Note that it ends up having to permit redefinition of functions so
that they can all be emitted. Additionally, all versions of the function
must be emitted, so this also manages that.
Note that this includes some additional rules that GCC does not, since
defining something as a MultiVersion function after a usage has been made illegal.
The only 'history rewriting' that happens is if a function is emitted before
it has been converted to a multiversion'ed function, at which point its name
needs to be changed.
Function templates and virtual functions are NOT yet supported (not supported
in GCC either).
Additionally, constructors/destructors are disallowed, but the former is
planned.
llvm-svn: 322028
2018-01-09 05:34:17 +08:00
|
|
|
return foo_inline();
|
|
|
|
}
|
|
|
|
|
|
|
|
inline __attribute__((target("default"))) void foo_decls(void);
|
|
|
|
inline __attribute__((target("sse4.2"))) void foo_decls(void);
|
2022-02-15 22:27:12 +08:00
|
|
|
void bar3(void) {
|
Implement Attribute Target MultiVersioning
GCC's attribute 'target', in addition to being an optimization hint,
also allows function multiversioning. We currently have the former
implemented, this is the latter's implementation.
This works by enabling functions with the same name/signature to coexist,
so that they can all be emitted. Multiversion state is stored in the
FunctionDecl itself, and SemaDecl manages the definitions.
Note that it ends up having to permit redefinition of functions so
that they can all be emitted. Additionally, all versions of the function
must be emitted, so this also manages that.
Note that this includes some additional rules that GCC does not, since
defining something as a MultiVersion function after a usage has been made illegal.
The only 'history rewriting' that happens is if a function is emitted before
it has been converted to a multiversion'ed function, at which point its name
needs to be changed.
Function templates and virtual functions are NOT yet supported (not supported
in GCC either).
Additionally, constructors/destructors are disallowed, but the former is
planned.
llvm-svn: 322028
2018-01-09 05:34:17 +08:00
|
|
|
foo_decls();
|
|
|
|
}
|
|
|
|
inline __attribute__((target("default"))) void foo_decls(void) {}
|
|
|
|
inline __attribute__((target("sse4.2"))) void foo_decls(void) {}
|
|
|
|
|
2018-10-26 02:57:19 +08:00
|
|
|
inline __attribute__((target("default"))) void foo_multi(int i, double d) {}
|
|
|
|
inline __attribute__((target("avx,sse4.2"))) void foo_multi(int i, double d) {}
|
|
|
|
inline __attribute__((target("sse4.2,fma4"))) void foo_multi(int i, double d) {}
|
|
|
|
inline __attribute__((target("arch=ivybridge,fma4,sse4.2"))) void foo_multi(int i, double d) {}
|
2022-02-15 22:27:12 +08:00
|
|
|
void bar4(void) {
|
2018-10-26 02:57:19 +08:00
|
|
|
foo_multi(1, 5.0);
|
2018-01-17 12:46:04 +08:00
|
|
|
}
|
|
|
|
|
2018-11-29 04:58:43 +08:00
|
|
|
int fwd_decl_default(void);
|
|
|
|
int __attribute__((target("default"))) fwd_decl_default(void) { return 2; }
|
|
|
|
|
|
|
|
int fwd_decl_avx(void);
|
|
|
|
int __attribute__((target("avx"))) fwd_decl_avx(void) { return 2; }
|
|
|
|
int __attribute__((target("default"))) fwd_decl_avx(void) { return 2; }
|
|
|
|
|
2022-02-15 22:27:12 +08:00
|
|
|
void bar5(void) {
|
2018-11-29 04:58:43 +08:00
|
|
|
fwd_decl_default();
|
|
|
|
fwd_decl_avx();
|
|
|
|
}
|
|
|
|
|
2020-03-09 23:06:58 +08:00
|
|
|
int __attribute__((target("avx"))) changed_to_mv(void) { return 0;}
|
|
|
|
int __attribute__((target("fma4"))) changed_to_mv(void) { return 1;}
|
|
|
|
|
2020-03-10 01:15:45 +08:00
|
|
|
__attribute__((target("default"), used)) inline void foo_used(int i, double d) {}
|
|
|
|
__attribute__((target("avx,sse4.2"))) inline void foo_used(int i, double d) {}
|
|
|
|
|
|
|
|
__attribute__((target("default"))) inline void foo_used2(int i, double d) {}
|
|
|
|
__attribute__((target("avx,sse4.2"), used)) inline void foo_used2(int i, double d) {}
|
|
|
|
|
2021-04-20 22:35:57 +08:00
|
|
|
// PR50025:
|
|
|
|
static void must_be_emitted(void) {}
|
|
|
|
inline __attribute__((target("default"))) void pr50025(void) { must_be_emitted(); }
|
2022-02-15 22:27:12 +08:00
|
|
|
void calls_pr50025(void) { pr50025(); }
|
2021-04-20 22:35:57 +08:00
|
|
|
|
|
|
|
// Also need to make sure we get other multiversion functions.
|
|
|
|
inline __attribute__((target("default"))) void pr50025b(void) { must_be_emitted(); }
|
|
|
|
inline __attribute__((target("default"))) void pr50025c(void) { pr50025b(); }
|
2022-02-15 22:27:12 +08:00
|
|
|
void calls_pr50025c(void) { pr50025c(); }
|
2021-04-20 22:35:57 +08:00
|
|
|
|
2022-03-26 06:35:16 +08:00
|
|
|
// LINUX: $foo.resolver = comdat any
|
|
|
|
// LINUX: $foo_inline.resolver = comdat any
|
|
|
|
// LINUX: $foo_decls.resolver = comdat any
|
|
|
|
// LINUX: $foo_multi.resolver = comdat any
|
|
|
|
// LINUX: $fwd_decl_default.resolver = comdat any
|
|
|
|
// LINUX: $fwd_decl_avx.resolver = comdat any
|
|
|
|
// LINUX: $pr50025.resolver = comdat any
|
|
|
|
// LINUX: $pr50025c.resolver = comdat any
|
|
|
|
// LINUX: $pr50025b.resolver = comdat any
|
|
|
|
|
|
|
|
// WINDOWS: $foo.resolver = comdat any
|
|
|
|
// WINDOWS: $foo_inline.resolver = comdat any
|
|
|
|
// WINDOWS: $foo_decls.resolver = comdat any
|
|
|
|
// WINDOWS: $foo_multi.resolver = comdat any
|
|
|
|
// WINDOWS: $fwd_decl_default.resolver = comdat any
|
|
|
|
// WINDOWS: $fwd_decl_avx.resolver = comdat any
|
|
|
|
// WINDOWS: $foo_used = comdat any
|
|
|
|
// WINDOWS: $foo_used2.avx_sse4.2 = comdat any
|
|
|
|
// WINDOWS: $pr50025.resolver = comdat any
|
|
|
|
// WINDOWS: $pr50025c.resolver = comdat any
|
|
|
|
// WINDOWS: $foo_inline.sse4.2 = comdat any
|
|
|
|
// WINDOWS: $foo_inline.arch_ivybridge = comdat any
|
|
|
|
// WINDOWS: $foo_inline = comdat any
|
|
|
|
// WINDOWS: $foo_decls = comdat any
|
|
|
|
// WINDOWS: $foo_decls.sse4.2 = comdat any
|
|
|
|
// WINDOWS: $foo_multi = comdat any
|
|
|
|
// WINDOWS: $foo_multi.avx_sse4.2 = comdat any
|
|
|
|
// WINDOWS: $foo_multi.fma4_sse4.2 = comdat any
|
|
|
|
// WINDOWS: $foo_multi.arch_ivybridge_fma4_sse4.2 = comdat any
|
|
|
|
// WINDOWS: $pr50025 = comdat any
|
|
|
|
// WINDOWS: $pr50025c = comdat any
|
|
|
|
// WINDOWS: $pr50025b.resolver = comdat any
|
|
|
|
// WINDOWS: $pr50025b = comdat any
|
|
|
|
|
|
|
|
|
Change some addUsedGlobal to addUsedOrCompilerUsedGlobal
An global value in the `llvm.used` list does not have GC root semantics on ELF targets.
This will be changed in a subsequent backend patch.
Change some `llvm.used` in the ELF code path to use `llvm.compiler.used` to
prevent undesired GC root semantics.
Change one extern "C" alias (due to `__attribute__((used))` in extern "C") to use `llvm.compiler.used` on all targets.
GNU ld has a rule "`__start_/__stop_` references from a live input section retain the associated C identifier name sections",
which LLD may drop entirely (currently refined to exclude SHF_LINK_ORDER/SHF_GROUP) in a future release (the rule makes it clumsy to GC metadata sections; D96914 added a way to try the potential future behavior).
For `llvm.used` global values defined in a C identifier name section, keep using `llvm.used` so that
the future LLD change will not affect them.
rnk kindly categorized the changes:
```
ObjC/blocks: this wants GC root semantics, since ObjC mainly runs on Mac.
MS C++ ABI stuff: wants GC root semantics, no change
OpenMP: unsure, but GC root semantics probably don't hurt
CodeGenModule: affected in this patch to *not* use GC root semantics so that __attribute__((used)) behavior remains the same on ELF, plus two other minor use cases that don't want GC semantics
Coverage: Probably want GC root semantics
CGExpr.cpp: refers to LTO, wants GC root
CGDeclCXX.cpp: one is MS ABI specific, so yes GC root, one is some other C++ init functionality, which should form GC roots (C++ initializers can have side effects and must run)
CGDecl.cpp: Changed in this patch for __attribute__((used))
```
Differential Revision: https://reviews.llvm.org/D97446
2021-02-27 02:42:07 +08:00
|
|
|
// LINUX: @llvm.compiler.used = appending global [2 x i8*] [i8* bitcast (void (i32, double)* @foo_used to i8*), i8* bitcast (void (i32, double)* @foo_used2.avx_sse4.2 to i8*)], section "llvm.metadata"
|
2020-03-10 01:15:45 +08:00
|
|
|
// WINDOWS: @llvm.used = appending global [2 x i8*] [i8* bitcast (void (i32, double)* @foo_used to i8*), i8* bitcast (void (i32, double)* @foo_used2.avx_sse4.2 to i8*)], section "llvm.metadata"
|
|
|
|
|
2022-03-26 06:35:16 +08:00
|
|
|
|
2020-02-04 02:09:39 +08:00
|
|
|
// LINUX: @foo.ifunc = weak_odr ifunc i32 (), i32 ()* ()* @foo.resolver
|
|
|
|
// LINUX: @foo_inline.ifunc = weak_odr ifunc i32 (), i32 ()* ()* @foo_inline.resolver
|
|
|
|
// LINUX: @foo_decls.ifunc = weak_odr ifunc void (), void ()* ()* @foo_decls.resolver
|
|
|
|
// LINUX: @foo_multi.ifunc = weak_odr ifunc void (i32, double), void (i32, double)* ()* @foo_multi.resolver
|
|
|
|
// LINUX: @fwd_decl_default.ifunc = weak_odr ifunc i32 (), i32 ()* ()* @fwd_decl_default.resolver
|
|
|
|
// LINUX: @fwd_decl_avx.ifunc = weak_odr ifunc i32 (), i32 ()* ()* @fwd_decl_avx.resolver
|
|
|
|
|
2020-12-31 16:27:11 +08:00
|
|
|
// LINUX: define{{.*}} i32 @foo.sse4.2()
|
2018-10-26 02:57:19 +08:00
|
|
|
// LINUX: ret i32 0
|
2020-12-31 16:27:11 +08:00
|
|
|
// LINUX: define{{.*}} i32 @foo.arch_ivybridge()
|
2018-10-26 02:57:19 +08:00
|
|
|
// LINUX: ret i32 1
|
2020-12-31 16:27:11 +08:00
|
|
|
// LINUX: define{{.*}} i32 @foo.arch_goldmont()
|
2020-06-10 06:25:46 +08:00
|
|
|
// LINUX: ret i32 3
|
2020-12-31 16:27:11 +08:00
|
|
|
// LINUX: define{{.*}} i32 @foo.arch_goldmont-plus()
|
2020-06-10 06:25:46 +08:00
|
|
|
// LINUX: ret i32 4
|
2020-12-31 16:27:11 +08:00
|
|
|
// LINUX: define{{.*}} i32 @foo.arch_tremont()
|
2020-06-10 06:25:46 +08:00
|
|
|
// LINUX: ret i32 5
|
2020-12-31 16:27:11 +08:00
|
|
|
// LINUX: define{{.*}} i32 @foo.arch_icelake-client()
|
2020-06-10 06:25:46 +08:00
|
|
|
// LINUX: ret i32 6
|
2020-12-31 16:27:11 +08:00
|
|
|
// LINUX: define{{.*}} i32 @foo.arch_icelake-server()
|
2020-06-10 06:25:46 +08:00
|
|
|
// LINUX: ret i32 7
|
2020-12-31 16:27:11 +08:00
|
|
|
// LINUX: define{{.*}} i32 @foo.arch_cooperlake()
|
2020-06-22 04:24:43 +08:00
|
|
|
// LINUX: ret i32 8
|
2020-12-31 16:27:11 +08:00
|
|
|
// LINUX: define{{.*}} i32 @foo.arch_tigerlake()
|
2020-06-22 04:24:43 +08:00
|
|
|
// LINUX: ret i32 9
|
2020-12-31 16:27:11 +08:00
|
|
|
// LINUX: define{{.*}} i32 @foo.arch_sapphirerapids()
|
[X86] Support -march=sapphirerapids
Support -march=sapphirerapids for x86.
Compare with Icelake Server, it includes 14 more new features. They are
amxtile, amxint8, amxbf16, avx512bf16, avx512vp2intersect, cldemote,
enqcmd, movdir64b, movdiri, ptwrite, serialize, shstk, tsxldtrk, waitpkg.
Reviewed By: craig.topper
Differential Revision: https://reviews.llvm.org/D86503
2020-08-25 12:27:02 +08:00
|
|
|
// LINUX: ret i32 10
|
2020-12-31 16:27:11 +08:00
|
|
|
// LINUX: define{{.*}} i32 @foo.arch_alderlake()
|
2020-10-25 00:00:33 +08:00
|
|
|
// LINUX: ret i32 11
|
2021-04-13 09:24:34 +08:00
|
|
|
// LINUX: define{{.*}} i32 @foo.arch_rocketlake()
|
|
|
|
// LINUX: ret i32 12
|
2020-12-31 16:27:11 +08:00
|
|
|
// LINUX: define{{.*}} i32 @foo()
|
2018-10-26 02:57:19 +08:00
|
|
|
// LINUX: ret i32 2
|
2020-12-31 16:27:11 +08:00
|
|
|
// LINUX: define{{.*}} i32 @bar()
|
2018-10-26 02:57:19 +08:00
|
|
|
// LINUX: call i32 @foo.ifunc()
|
|
|
|
|
|
|
|
// WINDOWS: define dso_local i32 @foo.sse4.2()
|
|
|
|
// WINDOWS: ret i32 0
|
|
|
|
// WINDOWS: define dso_local i32 @foo.arch_ivybridge()
|
|
|
|
// WINDOWS: ret i32 1
|
2020-06-10 06:25:46 +08:00
|
|
|
// WINDOWS: define dso_local i32 @foo.arch_goldmont()
|
|
|
|
// WINDOWS: ret i32 3
|
|
|
|
// WINDOWS: define dso_local i32 @foo.arch_goldmont-plus()
|
|
|
|
// WINDOWS: ret i32 4
|
|
|
|
// WINDOWS: define dso_local i32 @foo.arch_tremont()
|
|
|
|
// WINDOWS: ret i32 5
|
|
|
|
// WINDOWS: define dso_local i32 @foo.arch_icelake-client()
|
|
|
|
// WINDOWS: ret i32 6
|
|
|
|
// WINDOWS: define dso_local i32 @foo.arch_icelake-server()
|
|
|
|
// WINDOWS: ret i32 7
|
2021-07-29 13:27:40 +08:00
|
|
|
// WINDOWS: define dso_local i32 @foo.arch_cooperlake()
|
|
|
|
// WINDOWS: ret i32 8
|
|
|
|
// WINDOWS: define dso_local i32 @foo.arch_tigerlake()
|
|
|
|
// WINDOWS: ret i32 9
|
|
|
|
// WINDOWS: define dso_local i32 @foo.arch_sapphirerapids()
|
|
|
|
// WINDOWS: ret i32 10
|
|
|
|
// WINDOWS: define dso_local i32 @foo.arch_alderlake()
|
|
|
|
// WINDOWS: ret i32 11
|
|
|
|
// WINDOWS: define dso_local i32 @foo.arch_rocketlake()
|
|
|
|
// WINDOWS: ret i32 12
|
2018-10-26 02:57:19 +08:00
|
|
|
// WINDOWS: define dso_local i32 @foo()
|
|
|
|
// WINDOWS: ret i32 2
|
|
|
|
// WINDOWS: define dso_local i32 @bar()
|
|
|
|
// WINDOWS: call i32 @foo.resolver()
|
|
|
|
|
2019-09-11 09:54:48 +08:00
|
|
|
// LINUX: define weak_odr i32 ()* @foo.resolver() comdat
|
2018-10-26 02:57:19 +08:00
|
|
|
// LINUX: call void @__cpu_indicator_init()
|
|
|
|
// LINUX: ret i32 ()* @foo.arch_sandybridge
|
|
|
|
// LINUX: ret i32 ()* @foo.arch_ivybridge
|
|
|
|
// LINUX: ret i32 ()* @foo.sse4.2
|
|
|
|
// LINUX: ret i32 ()* @foo
|
|
|
|
|
2019-09-11 09:54:48 +08:00
|
|
|
// WINDOWS: define weak_odr dso_local i32 @foo.resolver() comdat
|
2018-10-26 02:57:19 +08:00
|
|
|
// WINDOWS: call void @__cpu_indicator_init()
|
|
|
|
// WINDOWS: call i32 @foo.arch_sandybridge
|
|
|
|
// WINDOWS: call i32 @foo.arch_ivybridge
|
|
|
|
// WINDOWS: call i32 @foo.sse4.2
|
|
|
|
// WINDOWS: call i32 @foo
|
|
|
|
|
2020-12-31 16:27:11 +08:00
|
|
|
// LINUX: define{{.*}} i32 @bar2()
|
2018-10-26 02:57:19 +08:00
|
|
|
// LINUX: call i32 @foo_inline.ifunc()
|
|
|
|
|
|
|
|
// WINDOWS: define dso_local i32 @bar2()
|
|
|
|
// WINDOWS: call i32 @foo_inline.resolver()
|
|
|
|
|
2019-09-11 09:54:48 +08:00
|
|
|
// LINUX: define weak_odr i32 ()* @foo_inline.resolver() comdat
|
2018-10-26 02:57:19 +08:00
|
|
|
// LINUX: call void @__cpu_indicator_init()
|
|
|
|
// LINUX: ret i32 ()* @foo_inline.arch_sandybridge
|
|
|
|
// LINUX: ret i32 ()* @foo_inline.arch_ivybridge
|
|
|
|
// LINUX: ret i32 ()* @foo_inline.sse4.2
|
|
|
|
// LINUX: ret i32 ()* @foo_inline
|
|
|
|
|
2019-09-11 09:54:48 +08:00
|
|
|
// WINDOWS: define weak_odr dso_local i32 @foo_inline.resolver() comdat
|
2018-10-26 02:57:19 +08:00
|
|
|
// WINDOWS: call void @__cpu_indicator_init()
|
|
|
|
// WINDOWS: call i32 @foo_inline.arch_sandybridge
|
|
|
|
// WINDOWS: call i32 @foo_inline.arch_ivybridge
|
|
|
|
// WINDOWS: call i32 @foo_inline.sse4.2
|
|
|
|
// WINDOWS: call i32 @foo_inline
|
|
|
|
|
2020-12-31 16:27:11 +08:00
|
|
|
// LINUX: define{{.*}} void @bar3()
|
2018-10-26 02:57:19 +08:00
|
|
|
// LINUX: call void @foo_decls.ifunc()
|
|
|
|
|
|
|
|
// WINDOWS: define dso_local void @bar3()
|
|
|
|
// WINDOWS: call void @foo_decls.resolver()
|
|
|
|
|
2019-09-11 09:54:48 +08:00
|
|
|
// LINUX: define weak_odr void ()* @foo_decls.resolver() comdat
|
2018-10-26 02:57:19 +08:00
|
|
|
// LINUX: ret void ()* @foo_decls.sse4.2
|
|
|
|
// LINUX: ret void ()* @foo_decls
|
|
|
|
|
2019-09-11 09:54:48 +08:00
|
|
|
// WINDOWS: define weak_odr dso_local void @foo_decls.resolver() comdat
|
2018-10-26 02:57:19 +08:00
|
|
|
// WINDOWS: call void @foo_decls.sse4.2
|
2018-12-07 23:06:43 +08:00
|
|
|
// WINDOWS: call void @foo_decls
|
2018-10-26 02:57:19 +08:00
|
|
|
|
2020-12-31 16:27:11 +08:00
|
|
|
// LINUX: define{{.*}} void @bar4()
|
2022-01-16 17:53:11 +08:00
|
|
|
// LINUX: call void @foo_multi.ifunc(i32 noundef 1, double noundef 5.{{[0+e]*}})
|
2018-10-26 02:57:19 +08:00
|
|
|
|
|
|
|
// WINDOWS: define dso_local void @bar4()
|
2022-01-16 17:53:11 +08:00
|
|
|
// WINDOWS: call void @foo_multi.resolver(i32 noundef 1, double noundef 5.{{[0+e]*}})
|
2018-10-26 02:57:19 +08:00
|
|
|
|
2019-09-11 09:54:48 +08:00
|
|
|
// LINUX: define weak_odr void (i32, double)* @foo_multi.resolver() comdat
|
2018-10-26 02:57:19 +08:00
|
|
|
// LINUX: and i32 %{{.*}}, 4352
|
|
|
|
// LINUX: icmp eq i32 %{{.*}}, 4352
|
|
|
|
// LINUX: ret void (i32, double)* @foo_multi.fma4_sse4.2
|
|
|
|
// LINUX: icmp eq i32 %{{.*}}, 12
|
|
|
|
// LINUX: and i32 %{{.*}}, 4352
|
|
|
|
// LINUX: icmp eq i32 %{{.*}}, 4352
|
|
|
|
// LINUX: ret void (i32, double)* @foo_multi.arch_ivybridge_fma4_sse4.2
|
|
|
|
// LINUX: and i32 %{{.*}}, 768
|
|
|
|
// LINUX: icmp eq i32 %{{.*}}, 768
|
|
|
|
// LINUX: ret void (i32, double)* @foo_multi.avx_sse4.2
|
|
|
|
// LINUX: ret void (i32, double)* @foo_multi
|
|
|
|
|
2019-09-11 09:54:48 +08:00
|
|
|
// WINDOWS: define weak_odr dso_local void @foo_multi.resolver(i32 %0, double %1) comdat
|
2018-10-26 02:57:19 +08:00
|
|
|
// WINDOWS: and i32 %{{.*}}, 4352
|
|
|
|
// WINDOWS: icmp eq i32 %{{.*}}, 4352
|
|
|
|
// WINDOWS: call void @foo_multi.fma4_sse4.2(i32 %0, double %1)
|
|
|
|
// WINDOWS-NEXT: ret void
|
|
|
|
// WINDOWS: icmp eq i32 %{{.*}}, 12
|
|
|
|
// WINDOWS: and i32 %{{.*}}, 4352
|
|
|
|
// WINDOWS: icmp eq i32 %{{.*}}, 4352
|
|
|
|
// WINDOWS: call void @foo_multi.arch_ivybridge_fma4_sse4.2(i32 %0, double %1)
|
|
|
|
// WINDOWS-NEXT: ret void
|
|
|
|
// WINDOWS: and i32 %{{.*}}, 768
|
|
|
|
// WINDOWS: icmp eq i32 %{{.*}}, 768
|
|
|
|
// WINDOWS: call void @foo_multi.avx_sse4.2(i32 %0, double %1)
|
|
|
|
// WINDOWS-NEXT: ret void
|
|
|
|
// WINDOWS: call void @foo_multi(i32 %0, double %1)
|
|
|
|
// WINDOWS-NEXT: ret void
|
|
|
|
|
2020-12-31 16:27:11 +08:00
|
|
|
// LINUX: define{{.*}} i32 @fwd_decl_default()
|
2018-11-29 04:58:43 +08:00
|
|
|
// LINUX: ret i32 2
|
2020-12-31 16:27:11 +08:00
|
|
|
// LINUX: define{{.*}} i32 @fwd_decl_avx.avx()
|
2018-11-29 04:58:43 +08:00
|
|
|
// LINUX: ret i32 2
|
2020-12-31 16:27:11 +08:00
|
|
|
// LINUX: define{{.*}} i32 @fwd_decl_avx()
|
2018-11-29 04:58:43 +08:00
|
|
|
// LINUX: ret i32 2
|
2018-10-26 02:57:19 +08:00
|
|
|
|
2018-11-29 04:58:43 +08:00
|
|
|
// WINDOWS: define dso_local i32 @fwd_decl_default()
|
|
|
|
// WINDOWS: ret i32 2
|
|
|
|
// WINDOWS: define dso_local i32 @fwd_decl_avx.avx()
|
|
|
|
// WINDOWS: ret i32 2
|
|
|
|
// WINDOWS: define dso_local i32 @fwd_decl_avx()
|
|
|
|
// WINDOWS: ret i32 2
|
|
|
|
|
2020-12-31 16:27:11 +08:00
|
|
|
// LINUX: define{{.*}} void @bar5()
|
2018-11-29 04:58:43 +08:00
|
|
|
// LINUX: call i32 @fwd_decl_default.ifunc()
|
|
|
|
// LINUX: call i32 @fwd_decl_avx.ifunc()
|
|
|
|
|
|
|
|
// WINDOWS: define dso_local void @bar5()
|
|
|
|
// WINDOWS: call i32 @fwd_decl_default.resolver()
|
|
|
|
// WINDOWS: call i32 @fwd_decl_avx.resolver()
|
|
|
|
|
2019-09-11 09:54:48 +08:00
|
|
|
// LINUX: define weak_odr i32 ()* @fwd_decl_default.resolver() comdat
|
2018-11-29 04:58:43 +08:00
|
|
|
// LINUX: call void @__cpu_indicator_init()
|
|
|
|
// LINUX: ret i32 ()* @fwd_decl_default
|
2019-09-11 09:54:48 +08:00
|
|
|
// LINUX: define weak_odr i32 ()* @fwd_decl_avx.resolver() comdat
|
2018-11-29 04:58:43 +08:00
|
|
|
// LINUX: call void @__cpu_indicator_init()
|
|
|
|
// LINUX: ret i32 ()* @fwd_decl_avx.avx
|
|
|
|
// LINUX: ret i32 ()* @fwd_decl_avx
|
|
|
|
|
2019-09-11 09:54:48 +08:00
|
|
|
// WINDOWS: define weak_odr dso_local i32 @fwd_decl_default.resolver() comdat
|
2018-11-29 04:58:43 +08:00
|
|
|
// WINDOWS: call void @__cpu_indicator_init()
|
|
|
|
// WINDOWS: call i32 @fwd_decl_default
|
2019-09-11 09:54:48 +08:00
|
|
|
// WINDOWS: define weak_odr dso_local i32 @fwd_decl_avx.resolver() comdat
|
2018-11-29 04:58:43 +08:00
|
|
|
// WINDOWS: call void @__cpu_indicator_init()
|
|
|
|
// WINDOWS: call i32 @fwd_decl_avx.avx
|
|
|
|
// WINDOWS: call i32 @fwd_decl_avx
|
|
|
|
|
2020-12-31 16:27:11 +08:00
|
|
|
// LINUX: define{{.*}} i32 @changed_to_mv.avx()
|
|
|
|
// LINUX: define{{.*}} i32 @changed_to_mv.fma4()
|
2020-03-09 23:06:58 +08:00
|
|
|
|
|
|
|
// WINDOWS: define dso_local i32 @changed_to_mv.avx()
|
|
|
|
// WINDOWS: define dso_local i32 @changed_to_mv.fma4()
|
|
|
|
|
2022-01-16 17:53:11 +08:00
|
|
|
// LINUX: define linkonce void @foo_used(i32 noundef %{{.*}}, double noundef %{{.*}})
|
2020-03-10 01:15:45 +08:00
|
|
|
// LINUX-NOT: @foo_used.avx_sse4.2(
|
|
|
|
// LINUX-NOT: @foo_used2(
|
2022-01-16 17:53:11 +08:00
|
|
|
// LINUX: define linkonce void @foo_used2.avx_sse4.2(i32 noundef %{{.*}}, double noundef %{{.*}})
|
2020-03-10 01:15:45 +08:00
|
|
|
|
2022-01-16 17:53:11 +08:00
|
|
|
// WINDOWS: define linkonce_odr dso_local void @foo_used(i32 noundef %{{.*}}, double noundef %{{.*}})
|
2020-03-10 01:15:45 +08:00
|
|
|
// WINDOWS-NOT: @foo_used.avx_sse4.2(
|
|
|
|
// WINDOWS-NOT: @foo_used2(
|
2022-01-16 17:53:11 +08:00
|
|
|
// WINDOWS: define linkonce_odr dso_local void @foo_used2.avx_sse4.2(i32 noundef %{{.*}}, double noundef %{{.*}})
|
2020-03-10 01:15:45 +08:00
|
|
|
|
2018-11-29 04:58:43 +08:00
|
|
|
// LINUX: declare i32 @foo.arch_sandybridge()
|
2018-10-26 02:57:19 +08:00
|
|
|
// WINDOWS: declare dso_local i32 @foo.arch_sandybridge()
|
|
|
|
|
2020-02-04 02:09:39 +08:00
|
|
|
// LINUX: define linkonce i32 @foo_inline.sse4.2()
|
2018-10-26 02:57:19 +08:00
|
|
|
// LINUX: ret i32 0
|
|
|
|
|
|
|
|
// WINDOWS: define linkonce_odr dso_local i32 @foo_inline.sse4.2()
|
|
|
|
// WINDOWS: ret i32 0
|
|
|
|
|
|
|
|
// LINUX: declare i32 @foo_inline.arch_sandybridge()
|
|
|
|
|
|
|
|
// WINDOWS: declare dso_local i32 @foo_inline.arch_sandybridge()
|
|
|
|
|
2020-02-04 02:09:39 +08:00
|
|
|
// LINUX: define linkonce i32 @foo_inline.arch_ivybridge()
|
2018-12-07 22:56:50 +08:00
|
|
|
// LINUX: ret i32 1
|
2020-02-04 02:09:39 +08:00
|
|
|
// LINUX: define linkonce i32 @foo_inline()
|
2018-12-07 22:56:50 +08:00
|
|
|
// LINUX: ret i32 2
|
|
|
|
|
|
|
|
// WINDOWS: define linkonce_odr dso_local i32 @foo_inline.arch_ivybridge()
|
|
|
|
// WINDOWS: ret i32 1
|
|
|
|
// WINDOWS: define linkonce_odr dso_local i32 @foo_inline()
|
|
|
|
// WINDOWS: ret i32 2
|
|
|
|
|
2020-02-04 02:09:39 +08:00
|
|
|
// LINUX: define linkonce void @foo_decls()
|
|
|
|
// LINUX: define linkonce void @foo_decls.sse4.2()
|
2018-12-07 22:56:50 +08:00
|
|
|
|
|
|
|
// WINDOWS: define linkonce_odr dso_local void @foo_decls()
|
|
|
|
// WINDOWS: define linkonce_odr dso_local void @foo_decls.sse4.2()
|
|
|
|
|
2022-01-16 17:53:11 +08:00
|
|
|
// LINUX: define linkonce void @foo_multi(i32 noundef %{{[^,]+}}, double noundef %{{[^\)]+}})
|
|
|
|
// LINUX: define linkonce void @foo_multi.avx_sse4.2(i32 noundef %{{[^,]+}}, double noundef %{{[^\)]+}})
|
|
|
|
// LINUX: define linkonce void @foo_multi.fma4_sse4.2(i32 noundef %{{[^,]+}}, double noundef %{{[^\)]+}})
|
|
|
|
// LINUX: define linkonce void @foo_multi.arch_ivybridge_fma4_sse4.2(i32 noundef %{{[^,]+}}, double noundef %{{[^\)]+}})
|
2018-12-07 22:56:50 +08:00
|
|
|
|
2022-01-16 17:53:11 +08:00
|
|
|
// WINDOWS: define linkonce_odr dso_local void @foo_multi(i32 noundef %{{[^,]+}}, double noundef %{{[^\)]+}})
|
|
|
|
// WINDOWS: define linkonce_odr dso_local void @foo_multi.avx_sse4.2(i32 noundef %{{[^,]+}}, double noundef %{{[^\)]+}})
|
|
|
|
// WINDOWS: define linkonce_odr dso_local void @foo_multi.fma4_sse4.2(i32 noundef %{{[^,]+}}, double noundef %{{[^\)]+}})
|
|
|
|
// WINDOWS: define linkonce_odr dso_local void @foo_multi.arch_ivybridge_fma4_sse4.2(i32 noundef %{{[^,]+}}, double noundef %{{[^\)]+}})
|
2021-04-20 22:35:57 +08:00
|
|
|
|
|
|
|
// Ensure that we emit the 'static' function here.
|
|
|
|
// LINUX: define linkonce void @pr50025()
|
|
|
|
// LINUX: call void @must_be_emitted
|
|
|
|
// LINUX: define internal void @must_be_emitted()
|
2022-03-26 06:35:16 +08:00
|
|
|
// WINDOWS: define linkonce_odr dso_local void @pr50025() #{{[0-9]*}} comdat
|
2021-04-20 22:35:57 +08:00
|
|
|
// WINDOWS: call void @must_be_emitted
|
|
|
|
// WINDOWS: define internal void @must_be_emitted()
|
|
|
|
|
|
|
|
// LINUX: define linkonce void @pr50025c()
|
2022-03-26 06:35:16 +08:00
|
|
|
// LINUX: call void @pr50025b.ifunc()
|
|
|
|
// WINDOWS: define linkonce_odr dso_local void @pr50025c() #{{[0-9]*}} comdat
|
|
|
|
// WINDOWS: call void @pr50025b.resolver()
|
|
|
|
|
|
|
|
// LINUX: define weak_odr void ()* @pr50025b.resolver() comdat
|
|
|
|
// LINUX: ret void ()* @pr50025b
|
2021-04-20 22:35:57 +08:00
|
|
|
// LINUX: define linkonce void @pr50025b()
|
2022-03-26 06:35:16 +08:00
|
|
|
// LINUX: call void @must_be_emitted()
|
|
|
|
// WINDOWS: define weak_odr dso_local void @pr50025b.resolver() comdat
|
|
|
|
// WINDOWS: musttail call void @pr50025b()
|
|
|
|
// WINDOWS: define linkonce_odr dso_local void @pr50025b() #{{[0-9]*}} comdat
|
|
|
|
// WINDOWS: call void @must_be_emitted()
|