diff options
Diffstat (limited to 'test/CodeGenCXX')
-rw-r--r-- | test/CodeGenCXX/ms-inline-asm-fields.cpp | 25 | ||||
-rw-r--r-- | test/CodeGenCXX/optnone-and-attributes.cpp | 82 | ||||
-rw-r--r-- | test/CodeGenCXX/optnone-class-members.cpp | 164 | ||||
-rw-r--r-- | test/CodeGenCXX/optnone-def-decl.cpp | 5 | ||||
-rw-r--r-- | test/CodeGenCXX/optnone-templates.cpp | 104 |
5 files changed, 378 insertions, 2 deletions
diff --git a/test/CodeGenCXX/ms-inline-asm-fields.cpp b/test/CodeGenCXX/ms-inline-asm-fields.cpp index a78d511..6f32933 100644 --- a/test/CodeGenCXX/ms-inline-asm-fields.cpp +++ b/test/CodeGenCXX/ms-inline-asm-fields.cpp @@ -29,3 +29,28 @@ extern "C" int test_namespace_global() { __asm mov eax, asdf::a_global.a3.b2 } +template <bool Signed> +struct make_storage_type { + struct type { + struct B { + int a; + int x; + } b; + }; +}; + +template <bool Signed> +struct msvc_dcas_x86 { + typedef typename make_storage_type<Signed>::type storage_type; + void store() __asm("PR26001") { + storage_type p; + __asm mov edx, p.b.x; + } +}; + +template void msvc_dcas_x86<false>::store(); +// CHECK: define weak_odr void @"\01PR26001"( +// CHECK: %[[P:.*]] = alloca %"struct.make_storage_type<false>::type", align 4 +// CHECK: %[[B:.*]] = getelementptr inbounds %"struct.make_storage_type<false>::type", %"struct.make_storage_type<false>::type"* %[[P]], i32 0, i32 0 +// CHECK: %[[X:.*]] = getelementptr inbounds %"struct.make_storage_type<false>::type::B", %"struct.make_storage_type<false>::type::B"* %[[B]], i32 0, i32 1 +// CHECK: call void asm sideeffect inteldialect "mov edx, dword ptr $0", "*m,~{edx},~{dirflag},~{fpsr},~{flags}"(i32* %[[X]]) diff --git a/test/CodeGenCXX/optnone-and-attributes.cpp b/test/CodeGenCXX/optnone-and-attributes.cpp new file mode 100644 index 0000000..56173b5 --- /dev/null +++ b/test/CodeGenCXX/optnone-and-attributes.cpp @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 < %s -triple i386-mingw32 -fms-extensions -emit-llvm -x c++ | FileCheck %s + +// optnone wins over inlinehint. +// Test that both func1 and func2 are marked optnone and noinline. + +// Definition with both optnone and inlinehint. +__attribute__((optnone)) +inline int func1(int a) { + return a + a + a + a; +} +// CHECK: @_Z5func1i({{.*}}) [[OPTNONE:#[0-9]+]] + +// optnone declaration, inlinehint definition. +__attribute__((optnone)) +int func2(int a); + +inline int func2(int a) { + return a + a + a + a; +} +// CHECK: @_Z5func2i({{.*}}) [[OPTNONE]] + +// Keep alive the definitions of func1 and func2. +int foo() { + int val = func1(1); + return val + func2(2); +} + +// optnone wins over minsize. +__attribute__((optnone)) +int func3(int a); + +__attribute__((minsize)) +int func3(int a) { + return a + a + a + a; +} +// Same attribute set as everything else, therefore no 'minsize'. +// CHECK: @_Z5func3i({{.*}}) [[OPTNONE]] + + +// Verify that noreturn is compatible with optnone. +__attribute__((noreturn)) +extern void exit_from_function(); + +__attribute__((noreturn)) __attribute((optnone)) +extern void noreturn_function(int a) { exit_from_function(); } +// CHECK: @_Z17noreturn_functioni({{.*}}) [[NORETURN:#[0-9]+]] + + +// Verify that __declspec(noinline) is compatible with optnone. +__declspec(noinline) __attribute__((optnone)) +void func4() { return; } +// CHECK: @_Z5func4v() [[OPTNONE]] + +__declspec(noinline) +extern void func5(); + +__attribute__((optnone)) +void func5() { return; } +// CHECK: @_Z5func5v() [[OPTNONE]] + + +// Verify also that optnone can be used on dllexport functions. +// Adding attribute optnone on a dllimport function has no effect. + +__attribute__((dllimport)) +__attribute__((optnone)) +int imported_optnone_func(int a); + +__attribute__((dllexport)) +__attribute__((optnone)) +int exported_optnone_func(int a) { + return imported_optnone_func(a); // use of imported func +} +// CHECK: @_Z21exported_optnone_funci({{.*}}) [[OPTNONE]] +// CHECK: declare dllimport {{.*}} @_Z21imported_optnone_funci({{.*}}) [[DLLIMPORT:#[0-9]+]] + + +// CHECK: attributes [[OPTNONE]] = { noinline {{.*}} optnone +// CHECK: attributes [[NORETURN]] = { noinline noreturn {{.*}} optnone + +// CHECK: attributes [[DLLIMPORT]] = +// CHECK-SAME-NOT: optnone diff --git a/test/CodeGenCXX/optnone-class-members.cpp b/test/CodeGenCXX/optnone-class-members.cpp new file mode 100644 index 0000000..147b821 --- /dev/null +++ b/test/CodeGenCXX/optnone-class-members.cpp @@ -0,0 +1,164 @@ +// RUN: %clang_cc1 < %s -triple %itanium_abi_triple -fms-extensions -emit-llvm -x c++ | FileCheck %s + +// Test attribute 'optnone' on methods: +// -- member functions; +// -- static member functions. + +// Verify that all methods of struct A are associated to the same attribute set. +// The attribute set shall contain attributes 'noinline' and 'optnone'. + +struct A { + // Definition of an optnone static method. + __attribute__((optnone)) + static int static_optnone_method(int a) { + return a + a; + } + // CHECK: @_ZN1A21static_optnone_methodEi({{.*}}) [[OPTNONE:#[0-9]+]] + + // Definition of an optnone normal method. + __attribute__((optnone)) + int optnone_method(int a) { + return a + a + a + a; + } + // CHECK: @_ZN1A14optnone_methodEi({{.*}}) [[OPTNONE]] + + // Declaration of an optnone method with out-of-line definition + // that doesn't say optnone. + __attribute__((optnone)) + int optnone_decl_method(int a); + + // Methods declared without attribute optnone; the definitions will + // have attribute optnone, and we verify optnone wins. + __forceinline static int static_forceinline_method(int a); + __attribute__((always_inline)) int alwaysinline_method(int a); + __attribute__((noinline)) int noinline_method(int a); + __attribute__((minsize)) int minsize_method(int a); +}; + +void foo() { + A a; + A::static_optnone_method(4); + a.optnone_method(14); + a.optnone_decl_method(12); + A::static_forceinline_method(5); + a.alwaysinline_method(5); + a.noinline_method(6); + a.minsize_method(7); +} + +// No attribute here, should still be on the definition. +int A::optnone_decl_method(int a) { + return a; +} +// CHECK: @_ZN1A19optnone_decl_methodEi({{.*}}) [[OPTNONE]] + +// optnone implies noinline; therefore attribute noinline is added to +// the set of function attributes. +// forceinline is instead translated as 'always_inline'. +// However 'noinline' wins over 'always_inline' and therefore +// the resulting attributes for this method are: noinline + optnone +__attribute__((optnone)) +int A::static_forceinline_method(int a) { + return a + a + a + a; +} +// CHECK: @_ZN1A25static_forceinline_methodEi({{.*}}) [[OPTNONE]] + +__attribute__((optnone)) +int A::alwaysinline_method(int a) { + return a + a + a + a; +} +// CHECK: @_ZN1A19alwaysinline_methodEi({{.*}}) [[OPTNONE]] + +// 'noinline' + 'noinline and optnone' = 'noinline and optnone' +__attribute__((optnone)) +int A::noinline_method(int a) { + return a + a + a + a; +} +// CHECK: @_ZN1A15noinline_methodEi({{.*}}) [[OPTNONE]] + +// 'optnone' wins over 'minsize' +__attribute__((optnone)) +int A::minsize_method(int a) { + return a + a + a + a; +} +// CHECK: @_ZN1A14minsize_methodEi({{.*}}) [[OPTNONE]] + + +// Test attribute 'optnone' on methods: +// -- pure virtual functions +// -- base virtual and derived virtual +// -- base virtual but not derived virtual +// -- optnone methods redefined in override + +// A method defined in override doesn't inherit the function attributes of the +// superclass method. + +struct B { + virtual int pure_virtual(int a) = 0; + __attribute__((optnone)) + virtual int pure_virtual_with_optnone(int a) = 0; + + virtual int base(int a) { + return a + a + a + a; + } + + __attribute__((optnone)) + virtual int optnone_base(int a) { + return a + a + a + a; + } + + __attribute__((optnone)) + virtual int only_base_virtual(int a) { + return a + a; + } +}; + +struct C : public B { + __attribute__((optnone)) + virtual int pure_virtual(int a) { + return a + a + a + a; + } + + virtual int pure_virtual_with_optnone(int a) { + return a + a + a + a; + } + + __attribute__((optnone)) + virtual int base(int a) { + return a + a; + } + + virtual int optnone_base(int a) { + return a + a; + } + + int only_base_virtual(int a) { + return a + a + a + a; + } +}; + +int bar() { + C c; + int result; + result = c.pure_virtual(3); + result += c.pure_virtual_with_optnone(2); + result += c.base(5); + result += c.optnone_base(7); + result += c.only_base_virtual(9); + return result; +} + +// CHECK: @_ZN1C12pure_virtualEi({{.*}}) {{.*}} [[OPTNONE]] +// CHECK: @_ZN1C25pure_virtual_with_optnoneEi({{.*}}) {{.*}} [[NORMAL:#[0-9]+]] +// CHECK: @_ZN1C4baseEi({{.*}}) {{.*}} [[OPTNONE]] +// CHECK: @_ZN1C12optnone_baseEi({{.*}}) {{.*}} [[NORMAL]] +// CHECK: @_ZN1C17only_base_virtualEi({{.*}}) {{.*}} [[NORMAL]] +// CHECK: @_ZN1B4baseEi({{.*}}) {{.*}} [[NORMAL]] +// CHECK: @_ZN1B12optnone_baseEi({{.*}}) {{.*}} [[OPTNONE]] +// CHECK: @_ZN1B17only_base_virtualEi({{.*}}) {{.*}} [[OPTNONE]] + + +// CHECK: attributes [[NORMAL]] = +// CHECK-SAME-NOT: noinline +// CHECK-SAME-NOT: optnone +// CHECK: attributes [[OPTNONE]] = {{.*}} noinline {{.*}} optnone diff --git a/test/CodeGenCXX/optnone-def-decl.cpp b/test/CodeGenCXX/optnone-def-decl.cpp index ab6eb3f..cb3a677 100644 --- a/test/CodeGenCXX/optnone-def-decl.cpp +++ b/test/CodeGenCXX/optnone-def-decl.cpp @@ -90,5 +90,6 @@ int user_of_forceinline_optnone_function() { // CHECK: @_Z28forceinline_optnone_functionii({{.*}}) [[OPTNONE]] // CHECK: attributes [[OPTNONE]] = { noinline nounwind optnone {{.*}} } -// CHECK: attributes [[NORMAL]] = { nounwind {{.*}} } - +// CHECK: attributes [[NORMAL]] = +// CHECK-SAME-NOT: noinline +// CHECK-SAME-NOT: optnone diff --git a/test/CodeGenCXX/optnone-templates.cpp b/test/CodeGenCXX/optnone-templates.cpp new file mode 100644 index 0000000..45a72b3 --- /dev/null +++ b/test/CodeGenCXX/optnone-templates.cpp @@ -0,0 +1,104 @@ +// RUN: %clang_cc1 %s -triple %itanium_abi_triple -std=c++11 -emit-llvm -o - | FileCheck %s + +// Test optnone on template instantiations. + +//-- Effect of optnone on generic add template function. + +template <typename T> T template_normal(T a) +{ + return a + a; +} + +template <typename T> __attribute__((optnone)) T template_optnone(T a) +{ + return a + a + a; +} + +// This function should cause instantiations of each template, one marked +// with the 'optnone' attribute. +int container(int i) +{ + return template_normal<int>(i) + template_optnone<int>(i); +} + +// CHECK: @_Z15template_normalIiET_S0_({{.*}}) [[NORMAL:#[0-9]+]] +// CHECK: @_Z16template_optnoneIiET_S0_({{.*}}) [[OPTNONE:#[0-9]+]] + + +//-- Effect of optnone on a partial specialization. +// FIRST TEST: a method becomes marked with optnone in the specialization. + +template <typename T, typename U> class template_normal_base { +public: + T method(T t, U u) + { + return t + static_cast<T>(u); + } +}; + +template <typename U> class template_normal_base<int, U> +{ +public: + __attribute__((optnone)) int method (int t, U u) + { + return t - static_cast<int>(u); + } +}; + +// This function should cause an instantiation of the full template (whose +// method is not marked optnone) and an instantiation of the partially +// specialized template (whose method is marked optnone). +void container2() +{ + int y = 2; + float z = 3.0; + template_normal_base<float, int> class_normal; + template_normal_base<int, float> class_optnone; + float r1 = class_normal.method(z, y); + float r2 = class_optnone.method(y, z); +} + +// CHECK: @_ZN20template_normal_baseIfiE6methodEfi({{.*}}) [[NORMAL]] +// CHECK: @_ZN20template_normal_baseIifE6methodEif({{.*}}) [[OPTNONE]] + + +//-- Effect of optnone on a partial specialization. +// SECOND TEST: a method loses optnone in the specialization. + +template <typename T, typename U> class template_optnone_base { +public: + __attribute__((optnone)) T method(T t, U u) + { + return t + static_cast<T>(u); + } +}; + +template <typename U> class template_optnone_base<int, U> +{ +public: + int method (int t, U u) + { + return t - static_cast<int>(u); + } +}; + +// This function should cause an instantiation of the full template (whose +// method is marked optnone) and an instantiation of the partially +// specialized template (whose method is not marked optnone). +void container3() +{ + int y = 2; + float z = 3.0; + template_optnone_base<float, int> class_optnone; + template_optnone_base<int, float> class_normal; + float r1 = class_optnone.method(z, y); + float r2 = class_normal.method(y, z); +} + +// CHECK: @_ZN21template_optnone_baseIfiE6methodEfi({{.*}}) [[OPTNONE]] +// CHECK: @_ZN21template_optnone_baseIifE6methodEif({{.*}}) [[NORMAL]] + + +// CHECK: attributes [[NORMAL]] = +// CHECK-SAME-NOT: optnone +// CHECK: attributes [[OPTNONE]] = {{.*}} optnone |