diff options
Diffstat (limited to 'test/CodeGenCXX')
| -rw-r--r-- | test/CodeGenCXX/dllexport.cpp | 29 | ||||
| -rw-r--r-- | test/CodeGenCXX/dllimport.cpp | 35 | ||||
| -rw-r--r-- | test/CodeGenCXX/pointers-to-data-members.cpp | 10 | ||||
| -rw-r--r-- | test/CodeGenCXX/pragma-loop.cpp | 191 | ||||
| -rw-r--r-- | test/CodeGenCXX/pragma-unroll.cpp | 99 | ||||
| -rw-r--r-- | test/CodeGenCXX/stack-reuse-miscompile.cpp | 36 | ||||
| -rw-r--r-- | test/CodeGenCXX/stack-reuse.cpp | 146 | ||||
| -rw-r--r-- | test/CodeGenCXX/x86_64-arguments-avx.cpp | 37 |
8 files changed, 576 insertions, 7 deletions
diff --git a/test/CodeGenCXX/dllexport.cpp b/test/CodeGenCXX/dllexport.cpp index 3a1a3ffd871ec..477e7dcf0b53e 100644 --- a/test/CodeGenCXX/dllexport.cpp +++ b/test/CodeGenCXX/dllexport.cpp @@ -691,10 +691,13 @@ extern template struct ExplicitInstantiationDeclExportedTemplate<int>; USEMEMFUNC(ExplicitInstantiationDeclExportedTemplate<int>, f); // M32-DAG: {{declare|define available_externally}} x86_thiscallcc void @"\01?f@?$ExplicitInstantiationDeclExportedTemplate@H@@QAEXXZ" -template <typename T> struct ExplicitInstantiationDeclExportedDefTemplate { void f() {} }; +template <typename T> struct ExplicitInstantiationDeclExportedDefTemplate { void f() {} ExplicitInstantiationDeclExportedDefTemplate() {} }; extern template struct ExplicitInstantiationDeclExportedDefTemplate<int>; template struct __declspec(dllexport) ExplicitInstantiationDeclExportedDefTemplate<int>; +USEMEMFUNC(ExplicitInstantiationDeclExportedDefTemplate<int>, f); // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$ExplicitInstantiationDeclExportedDefTemplate@H@@QAEXXZ" +// M32-DAG: define weak_odr dllexport x86_thiscallcc %struct.ExplicitInstantiationDeclExportedDefTemplate* @"\01??0?$ExplicitInstantiationDeclExportedDefTemplate@H@@QAE@XZ" +// G32-DAG: define weak_odr x86_thiscallcc void @_ZN44ExplicitInstantiationDeclExportedDefTemplateIiE1fEv namespace { struct InternalLinkageType {}; } struct __declspec(dllexport) PR23308 { @@ -704,6 +707,11 @@ void PR23308::f(InternalLinkageType*) {} long use(PR23308* p) { p->f(nullptr); } // M32-DAG: define internal x86_thiscallcc void @"\01?f@PR23308@@QAEXPAUInternalLinkageType@?A@@@Z" +template <typename T> struct PR23770BaseTemplate { void f() {} }; +template <typename T> struct PR23770DerivedTemplate : PR23770BaseTemplate<int> {}; +extern template struct PR23770DerivedTemplate<int>; +template struct __declspec(dllexport) PR23770DerivedTemplate<int>; +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$PR23770BaseTemplate@H@@QAEXXZ" //===----------------------------------------------------------------------===// @@ -754,11 +762,11 @@ USEMEMFUNC(DerivedFromImportedTemplate, func) // M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$ImportedClassTemplate@H@@QAEXXZ" // G32-DAG: declare dllimport x86_thiscallcc void @_ZN21ImportedClassTemplateIiE4funcEv -// Base class already instantiated without dll attribute. +// Base class already implicitly instantiated without dll attribute. struct DerivedFromTemplateD : public ClassTemplate<double> {}; struct __declspec(dllexport) DerivedFromTemplateD2 : public ClassTemplate<double> {}; USEMEMFUNC(DerivedFromTemplateD2, func) -// M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?func@?$ClassTemplate@N@@QAEXXZ" +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ClassTemplate@N@@QAEXXZ" // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ClassTemplateIdE4funcEv // MS: Base class already instantiated with different dll attribute. @@ -811,3 +819,18 @@ struct __declspec(dllexport) BottomClass : public MiddleClass<int> { }; USEMEMFUNC(BottomClass, func) // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$TopClass@H@@QAEXXZ" // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN8TopClassIiE4funcEv + +template <typename T> struct ExplicitInstantiationDeclTemplateBase { void func() {} }; +extern template struct ExplicitInstantiationDeclTemplateBase<int>; +struct __declspec(dllexport) DerivedFromExplicitInstantiationDeclTemplateBase : public ExplicitInstantiationDeclTemplateBase<int> {}; +template struct ExplicitInstantiationDeclTemplateBase<int>; +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ExplicitInstantiationDeclTemplateBase@H@@QAEXXZ" +// G32-DAG: define weak_odr x86_thiscallcc void @_ZN37ExplicitInstantiationDeclTemplateBaseIiE4funcEv + +template <typename T> struct ExplicitInstantiationDeclTemplateBase2 { void func() {} }; +extern template struct ExplicitInstantiationDeclTemplateBase2<int>; +struct __declspec(dllexport) DerivedFromExplicitInstantiationDeclTemplateBase2 : public ExplicitInstantiationDeclTemplateBase2<int> {}; +template struct __declspec(dllimport) ExplicitInstantiationDeclTemplateBase2<int>; +USEMEMFUNC(ExplicitInstantiationDeclTemplateBase2<int>, func) +// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ExplicitInstantiationDeclTemplateBase2@H@@QAEXXZ" +// G32-DAG: define weak_odr x86_thiscallcc void @_ZN38ExplicitInstantiationDeclTemplateBase2IiE4funcEv diff --git a/test/CodeGenCXX/dllimport.cpp b/test/CodeGenCXX/dllimport.cpp index 6de856017b549..0f15ff0291b90 100644 --- a/test/CodeGenCXX/dllimport.cpp +++ b/test/CodeGenCXX/dllimport.cpp @@ -724,18 +724,29 @@ template struct __declspec(dllimport) ExplicitlyInstantiatedWithDifferentAttr<in USEMEMFUNC(ExplicitlyInstantiatedWithDifferentAttr<int>, f); // M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?f@?$ExplicitlyInstantiatedWithDifferentAttr@H@@QAEXXZ" -template <typename T> struct ExplicitInstantiationDeclImportedDefTemplate { void f() {} }; +template <typename T> struct ExplicitInstantiationDeclImportedDefTemplate { void f() {} ExplicitInstantiationDeclImportedDefTemplate() {}}; extern template struct ExplicitInstantiationDeclImportedDefTemplate<int>; template struct __declspec(dllimport) ExplicitInstantiationDeclImportedDefTemplate<int>; +USECLASS(ExplicitInstantiationDeclImportedDefTemplate<int>); USEMEMFUNC(ExplicitInstantiationDeclImportedDefTemplate<int>, f); // M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?f@?$ExplicitInstantiationDeclImportedDefTemplate@H@@QAEXXZ" +// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc %struct.ExplicitInstantiationDeclImportedDefTemplate* @"\01??0?$ExplicitInstantiationDeclImportedDefTemplate@H@@QAE@XZ" +// G32-DAG: define weak_odr x86_thiscallcc void @_ZN44ExplicitInstantiationDeclImportedDefTemplateIiE1fEv -template <typename T> struct __declspec(dllimport) ExplicitInstantiationDeclExportedDefImportedTemplate { void f() {} }; +template <typename T> struct __declspec(dllimport) ExplicitInstantiationDeclExportedDefImportedTemplate { void f() {} ExplicitInstantiationDeclExportedDefImportedTemplate() {} }; extern template struct __declspec(dllimport) ExplicitInstantiationDeclExportedDefImportedTemplate <int>; template struct __declspec(dllexport) ExplicitInstantiationDeclExportedDefImportedTemplate<int>; +USECLASS(ExplicitInstantiationDeclExportedDefImportedTemplate<int>); USEMEMFUNC(ExplicitInstantiationDeclExportedDefImportedTemplate<int>, f); // M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?f@?$ExplicitInstantiationDeclExportedDefImportedTemplate@H@@QAEXXZ" +// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc %struct.ExplicitInstantiationDeclExportedDefImportedTemplate* @"\01??0?$ExplicitInstantiationDeclExportedDefImportedTemplate@H@@QAE@XZ" +template <typename T> struct PR23770BaseTemplate { void f() {} }; +template <typename T> struct PR23770DerivedTemplate : PR23770BaseTemplate<int> {}; +extern template struct PR23770DerivedTemplate<int>; +template struct __declspec(dllimport) PR23770DerivedTemplate<int>; +USEMEMFUNC(PR23770BaseTemplate<int>, f); +// M32-DAG: declare dllimport x86_thiscallcc void @"\01?f@?$PR23770BaseTemplate@H@@QAEXXZ" //===----------------------------------------------------------------------===// // Classes with template base classes @@ -781,11 +792,11 @@ USEMEMFUNC(ExportedClassTemplate<int>, func) // M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?func@?$ExportedClassTemplate@H@@QAEXXZ" // G32-DAG: define weak_odr dllexport x86_thiscallcc void @_ZN21ExportedClassTemplateIiE4funcEv -// Base class already instantiated without attribute. +// Base class already implicitly instantiated without attribute. struct DerivedFromTemplateD : public ClassTemplate<double> {}; struct __declspec(dllimport) DerivedFromTemplateD2 : public ClassTemplate<double> {}; USEMEMFUNC(ClassTemplate<double>, func) -// M32-DAG: define linkonce_odr x86_thiscallcc void @"\01?func@?$ClassTemplate@N@@QAEXXZ" +// M32-DAG: declare dllimport x86_thiscallcc void @"\01?func@?$ClassTemplate@N@@QAEXXZ" // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN13ClassTemplateIdE4funcEv // MS: Base class already instantiated with dfferent attribute. @@ -838,3 +849,19 @@ struct __declspec(dllimport) BottomClass : public MiddleClass<int> { }; USEMEMFUNC(TopClass<int>, func) // M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?func@?$TopClass@H@@QAEXXZ" // G32-DAG: define linkonce_odr x86_thiscallcc void @_ZN8TopClassIiE4funcEv + +template <typename T> struct ExplicitInstantiationDeclTemplateBase { void func() {} }; +extern template struct ExplicitInstantiationDeclTemplateBase<int>; +struct __declspec(dllimport) DerivedFromExplicitInstantiationDeclTemplateBase : public ExplicitInstantiationDeclTemplateBase<int> {}; +template struct ExplicitInstantiationDeclTemplateBase<int>; +USEMEMFUNC(ExplicitInstantiationDeclTemplateBase<int>, func) +// M32-DAG: declare dllimport x86_thiscallcc void @"\01?func@?$ExplicitInstantiationDeclTemplateBase@H@@QAEXXZ" +// G32-DAG: define weak_odr x86_thiscallcc void @_ZN37ExplicitInstantiationDeclTemplateBaseIiE4funcEv + +template <typename T> struct ExplicitInstantiationDeclTemplateBase2 { void func() {} }; +extern template struct ExplicitInstantiationDeclTemplateBase2<int>; +struct __declspec(dllimport) DerivedFromExplicitInstantiationDeclTemplateBase2 : public ExplicitInstantiationDeclTemplateBase2<int> {}; +template struct __declspec(dllexport) ExplicitInstantiationDeclTemplateBase2<int>; +USEMEMFUNC(ExplicitInstantiationDeclTemplateBase2<int>, func) +// M32-DAG: declare dllimport x86_thiscallcc void @"\01?func@?$ExplicitInstantiationDeclTemplateBase2@H@@QAEXXZ" +// G32-DAG: define weak_odr x86_thiscallcc void @_ZN38ExplicitInstantiationDeclTemplateBase2IiE4funcEv diff --git a/test/CodeGenCXX/pointers-to-data-members.cpp b/test/CodeGenCXX/pointers-to-data-members.cpp index 0f2ddaac23b17..94337d98a1956 100644 --- a/test/CodeGenCXX/pointers-to-data-members.cpp +++ b/test/CodeGenCXX/pointers-to-data-members.cpp @@ -285,4 +285,14 @@ S s; // CHECK-GLOBAL: @_ZN19FlexibleArrayMember1sE = global %"struct.FlexibleArrayMember::S" zeroinitializer, align 8 } +namespace IndirectPDM { +union U { + union { + int U::*m; + }; +}; +U u; +// CHECK-GLOBAL: @_ZN11IndirectPDM1uE = global %"union.IndirectPDM::U" { %union.anon { i64 -1 } }, align 8 +} + // CHECK-O3: attributes [[NUW]] = { nounwind readnone{{.*}} } diff --git a/test/CodeGenCXX/pragma-loop.cpp b/test/CodeGenCXX/pragma-loop.cpp new file mode 100644 index 0000000000000..dd40c1d72600e --- /dev/null +++ b/test/CodeGenCXX/pragma-loop.cpp @@ -0,0 +1,191 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm -o - %s | FileCheck %s + +// Verify while loop is recognized after sequence of pragma clang loop directives. +void while_test(int *List, int Length) { + // CHECK: define {{.*}} @_Z10while_test + int i = 0; + +#pragma clang loop vectorize(enable) +#pragma clang loop interleave_count(4) +#pragma clang loop vectorize_width(4) +#pragma clang loop unroll(full) + while (i < Length) { + // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_1:.*]] + List[i] = i * 2; + i++; + } +} + +// Verify do loop is recognized after multi-option pragma clang loop directive. +void do_test(int *List, int Length) { + int i = 0; + +#pragma clang loop vectorize_width(8) interleave_count(4) unroll(disable) + do { + // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_2:.*]] + List[i] = i * 2; + i++; + } while (i < Length); +} + +enum struct Tuner : short { Interleave = 4, Unroll = 8 }; + +// Verify for loop is recognized after sequence of pragma clang loop directives. +void for_test(int *List, int Length) { +#pragma clang loop interleave(enable) +#pragma clang loop interleave_count(static_cast<int>(Tuner::Interleave)) +#pragma clang loop unroll_count(static_cast<int>(Tuner::Unroll)) + for (int i = 0; i < Length; i++) { + // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_3:.*]] + List[i] = i * 2; + } +} + +// Verify c++11 for range loop is recognized after +// sequence of pragma clang loop directives. +void for_range_test() { + double List[100]; + +#pragma clang loop vectorize_width(2) interleave_count(2) + for (int i : List) { + // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_4:.*]] + List[i] = i; + } +} + +// Verify disable pragma clang loop directive generates correct metadata +void disable_test(int *List, int Length) { +#pragma clang loop vectorize(disable) unroll(disable) + for (int i = 0; i < Length; i++) { + // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_5:.*]] + List[i] = i * 2; + } +} + +#define VECWIDTH 2 +#define INTCOUNT 2 +#define UNROLLCOUNT 8 + +// Verify defines are correctly resolved in pragma clang loop directive +void for_define_test(int *List, int Length, int Value) { +#pragma clang loop vectorize_width(VECWIDTH) interleave_count(INTCOUNT) +#pragma clang loop unroll_count(UNROLLCOUNT) + for (int i = 0; i < Length; i++) { + // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_6:.*]] + List[i] = i * Value; + } +} + +// Verify constant expressions are handled correctly. +void for_contant_expression_test(int *List, int Length) { +#pragma clang loop vectorize_width(1 + 4) + for (int i = 0; i < Length; i++) { + // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_7:.*]] + List[i] = i; + } + +#pragma clang loop vectorize_width(3 + VECWIDTH) + for (int i = 0; i < Length; i++) { + // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_8:.*]] + List[i] += i; + } +} + +// Verify metadata is generated when template is used. +template <typename A> +void for_template_test(A *List, int Length, A Value) { +#pragma clang loop vectorize_width(8) interleave_count(8) unroll_count(8) + for (int i = 0; i < Length; i++) { + // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_9:.*]] + List[i] = i * Value; + } +} + +// Verify define is resolved correctly when template is used. +template <typename A, typename T> +void for_template_define_test(A *List, int Length, A Value) { + const T VWidth = VECWIDTH; + const T ICount = INTCOUNT; + const T UCount = UNROLLCOUNT; +#pragma clang loop vectorize_width(VWidth) interleave_count(ICount) +#pragma clang loop unroll_count(UCount) + for (int i = 0; i < Length; i++) { + // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_10:.*]] + List[i] = i * Value; + } +} + +// Verify templates and constant expressions are handled correctly. +template <typename A, int V, int I, int U> +void for_template_constant_expression_test(A *List, int Length) { +#pragma clang loop vectorize_width(V) interleave_count(I) unroll_count(U) + for (int i = 0; i < Length; i++) { + // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_11:.*]] + List[i] = i; + } + +#pragma clang loop vectorize_width(V * 2 + VECWIDTH) interleave_count(I * 2 + INTCOUNT) unroll_count(U * 2 + UNROLLCOUNT) + for (int i = 0; i < Length; i++) { + // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_12:.*]] + List[i] += i; + } + + const int Scale = 4; +#pragma clang loop vectorize_width(Scale * V) interleave_count(Scale * I) unroll_count(Scale * U) + for (int i = 0; i < Length; i++) { + // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_13:.*]] + List[i] += i; + } + +#pragma clang loop vectorize_width((Scale * V) + 2) + for (int i = 0; i < Length; i++) { + // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_14:.*]] + List[i] += i; + } +} + +#undef VECWIDTH +#undef INTCOUNT +#undef UNROLLCOUNT + +// Use templates defined above. Test verifies metadata is generated correctly. +void template_test(double *List, int Length) { + double Value = 10; + + for_template_test<double>(List, Length, Value); + for_template_define_test<double, int>(List, Length, Value); + for_template_constant_expression_test<double, 2, 4, 8>(List, Length); +} + +// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], ![[UNROLL_FULL:.*]], ![[WIDTH_4:.*]], ![[INTERLEAVE_4:.*]], ![[INTENABLE_1:.*]]} +// CHECK: ![[UNROLL_FULL]] = !{!"llvm.loop.unroll.full"} +// CHECK: ![[WIDTH_4]] = !{!"llvm.loop.vectorize.width", i32 4} +// CHECK: ![[INTERLEAVE_4]] = !{!"llvm.loop.interleave.count", i32 4} +// CHECK: ![[INTENABLE_1]] = !{!"llvm.loop.vectorize.enable", i1 true} +// CHECK: ![[LOOP_2]] = distinct !{![[LOOP_2:.*]], ![[UNROLL_DISABLE:.*]], ![[INTERLEAVE_4:.*]], ![[WIDTH_8:.*]]} +// CHECK: ![[UNROLL_DISABLE]] = !{!"llvm.loop.unroll.disable"} +// CHECK: ![[WIDTH_8]] = !{!"llvm.loop.vectorize.width", i32 8} +// CHECK: ![[LOOP_3]] = distinct !{![[LOOP_3]], ![[UNROLL_8:.*]], ![[INTERLEAVE_4:.*]], ![[ENABLE_1:.*]]} +// CHECK: ![[UNROLL_8]] = !{!"llvm.loop.unroll.count", i32 8} +// CHECK: ![[LOOP_4]] = distinct !{![[LOOP_4]], ![[INTERLEAVE_2:.*]], ![[WIDTH_2:.*]]} +// CHECK: ![[INTERLEAVE_2]] = !{!"llvm.loop.interleave.count", i32 2} +// CHECK: ![[WIDTH_2]] = !{!"llvm.loop.vectorize.width", i32 2} +// CHECK: ![[LOOP_5]] = distinct !{![[LOOP_5]], ![[UNROLL_DISABLE:.*]], ![[WIDTH_1:.*]]} +// CHECK: ![[WIDTH_1]] = !{!"llvm.loop.vectorize.width", i32 1} +// CHECK: ![[LOOP_6]] = distinct !{![[LOOP_6]], ![[UNROLL_8:.*]], ![[INTERLEAVE_2:.*]], ![[WIDTH_2:.*]]} +// CHECK: ![[LOOP_7]] = distinct !{![[LOOP_7]], ![[WIDTH_5:.*]]} +// CHECK: ![[WIDTH_5]] = !{!"llvm.loop.vectorize.width", i32 5} +// CHECK: ![[LOOP_8]] = distinct !{![[LOOP_8]], ![[WIDTH_5:.*]]} +// CHECK: ![[LOOP_9]] = distinct !{![[LOOP_9]], ![[UNROLL_8:.*]], ![[INTERLEAVE_8:.*]], ![[WIDTH_8:.*]]} +// CHECK: ![[INTERLEAVE_8]] = !{!"llvm.loop.interleave.count", i32 8} +// CHECK: ![[LOOP_10]] = distinct !{![[LOOP_10]], ![[UNROLL_8:.*]], ![[INTERLEAVE_2:.*]], ![[WIDTH_2:.*]]} +// CHECK: ![[LOOP_11]] = distinct !{![[LOOP_11]], ![[UNROLL_8:.*]], ![[INTERLEAVE_4:.*]], ![[WIDTH_2:.*]]} +// CHECK: ![[LOOP_12]] = distinct !{![[LOOP_12]], ![[UNROLL_24:.*]], ![[INTERLEAVE_10:.*]], ![[WIDTH_6:.*]]} +// CHECK: ![[UNROLL_24]] = !{!"llvm.loop.unroll.count", i32 24} +// CHECK: ![[INTERLEAVE_10]] = !{!"llvm.loop.interleave.count", i32 10} +// CHECK: ![[WIDTH_6]] = !{!"llvm.loop.vectorize.width", i32 6} +// CHECK: ![[LOOP_13]] = distinct !{![[LOOP_13]], ![[UNROLL_32:.*]], ![[INTERLEAVE_16:.*]], ![[WIDTH_8:.*]]} +// CHECK: ![[UNROLL_32]] = !{!"llvm.loop.unroll.count", i32 32} +// CHECK: ![[INTERLEAVE_16]] = !{!"llvm.loop.interleave.count", i32 16} +// CHECK: ![[LOOP_14]] = distinct !{![[LOOP_14]], ![[WIDTH_10:.*]]} +// CHECK: ![[WIDTH_10]] = !{!"llvm.loop.vectorize.width", i32 10} diff --git a/test/CodeGenCXX/pragma-unroll.cpp b/test/CodeGenCXX/pragma-unroll.cpp new file mode 100644 index 0000000000000..8b73fa6c8aab4 --- /dev/null +++ b/test/CodeGenCXX/pragma-unroll.cpp @@ -0,0 +1,99 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm -o - %s | FileCheck %s + +// Verify while loop is recognized after unroll pragma. +void while_test(int *List, int Length) { + // CHECK: define {{.*}} @_Z10while_test + int i = 0; + +#pragma unroll + while (i < Length) { + // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_1:.*]] + List[i] = i * 2; + i++; + } +} + +// Verify do loop is recognized after multi-option pragma clang loop directive. +void do_test(int *List, int Length) { + int i = 0; + +#pragma nounroll + do { + // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_2:.*]] + List[i] = i * 2; + i++; + } while (i < Length); +} + +// Verify for loop is recognized after unroll pragma. +void for_test(int *List, int Length) { +#pragma unroll 8 + for (int i = 0; i < Length; i++) { + // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_3:.*]] + List[i] = i * 2; + } +} + +// Verify c++11 for range loop is recognized after unroll pragma. +void for_range_test() { + double List[100]; + +#pragma unroll(4) + for (int i : List) { + // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_4:.*]] + List[i] = i; + } +} + +#define UNROLLCOUNT 8 + +// Verify defines are correctly resolved in unroll pragmas. +void for_define_test(int *List, int Length, int Value) { +#pragma unroll(UNROLLCOUNT) + for (int i = 0; i < Length; i++) { + // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_5:.*]] + List[i] = i * Value; + } +} + +// Verify metadata is generated when template is used. +template <typename A> +void for_template_test(A *List, int Length, A Value) { +#pragma unroll 8 + for (int i = 0; i < Length; i++) { + // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_6:.*]] + List[i] = i * Value; + } +} + +// Verify define is resolved correctly when template is used. +template <typename A> +void for_template_define_test(A *List, int Length, A Value) { +#pragma unroll(UNROLLCOUNT) + for (int i = 0; i < Length; i++) { + // CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_7:.*]] + List[i] = i * Value; + } +} + +#undef UNROLLCOUNT + +// Use templates defined above. Test verifies metadata is generated correctly. +void template_test(double *List, int Length) { + double Value = 10; + + for_template_test<double>(List, Length, Value); + for_template_define_test<double>(List, Length, Value); +} + +// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], ![[UNROLL_FULL:.*]]} +// CHECK: ![[UNROLL_FULL]] = !{!"llvm.loop.unroll.full"} +// CHECK: ![[LOOP_2]] = distinct !{![[LOOP_2:.*]], ![[UNROLL_DISABLE:.*]]} +// CHECK: ![[UNROLL_DISABLE]] = !{!"llvm.loop.unroll.disable"} +// CHECK: ![[LOOP_3]] = distinct !{![[LOOP_3]], ![[UNROLL_8:.*]]} +// CHECK: ![[UNROLL_8]] = !{!"llvm.loop.unroll.count", i32 8} +// CHECK: ![[LOOP_4]] = distinct !{![[LOOP_4]], ![[UNROLL_4:.*]]} +// CHECK: ![[UNROLL_4]] = !{!"llvm.loop.unroll.count", i32 4} +// CHECK: ![[LOOP_5]] = distinct !{![[LOOP_5]], ![[UNROLL_8:.*]]} +// CHECK: ![[LOOP_6]] = distinct !{![[LOOP_6]], ![[UNROLL_8:.*]]} +// CHECK: ![[LOOP_7]] = distinct !{![[LOOP_7]], ![[UNROLL_8:.*]]} diff --git a/test/CodeGenCXX/stack-reuse-miscompile.cpp b/test/CodeGenCXX/stack-reuse-miscompile.cpp new file mode 100644 index 0000000000000..63d15fd1e8c93 --- /dev/null +++ b/test/CodeGenCXX/stack-reuse-miscompile.cpp @@ -0,0 +1,36 @@ +// RUN: %clang -S -target armv7l-unknown-linux-gnueabihf -emit-llvm -O1 -mllvm -disable-llvm-optzns -S %s -o - | FileCheck %s + +// This test should not to generate llvm.lifetime.start/llvm.lifetime.end for +// f function because all temporary objects in this function are used for the +// final result + +class S { + char *ptr; + unsigned int len; +}; + +class T { + S left; + S right; + +public: + T(const char s[]); + T(S); + + T concat(const T &Suffix) const; + const char * str() const; +}; + +const char * f(S s) +{ +// CHECK: [[T1:%.*]] = alloca %class.T, align 4 +// CHECK: [[T2:%.*]] = alloca %class.T, align 4 +// CHECK: [[T3:%.*]] = alloca %class.T, align 4 +// CHECK: [[T4:%.*]] = call %class.T* @_ZN1TC1EPKc(%class.T* [[T1]], i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str, i32 0, i32 0)) +// CHECK: [[T5:%.*]] = call %class.T* @_ZN1TC1E1S(%class.T* [[T2]], [2 x i32] %{{.*}}) +// CHECK: call void @_ZNK1T6concatERKS_(%class.T* sret [[T3]], %class.T* [[T1]], %class.T* dereferenceable(16) [[T2]]) +// CHECK: [[T6:%.*]] = call i8* @_ZNK1T3strEv(%class.T* [[T3]]) +// CHECK: ret i8* [[T6]] + + return T("[").concat(T(s)).str(); +} diff --git a/test/CodeGenCXX/stack-reuse.cpp b/test/CodeGenCXX/stack-reuse.cpp new file mode 100644 index 0000000000000..a975f30a048a9 --- /dev/null +++ b/test/CodeGenCXX/stack-reuse.cpp @@ -0,0 +1,146 @@ +// RUN: %clang -target armv7l-unknown-linux-gnueabihf -S %s -o - -emit-llvm -O1 -disable-llvm-optzns | FileCheck %s + +// Stack should be reused when possible, no need to allocate two separate slots +// if they have disjoint lifetime. + +// Sizes of objects are related to previously existed threshold of 32. In case +// of S_large stack size is rounded to 40 bytes. + +// 32B +struct S_small { + int a[8]; +}; + +// 36B +struct S_large { + int a[9]; +}; + +// Helper class for lifetime scope absence testing +struct Combiner { + S_large a, b; + + Combiner(S_large); + Combiner f(); +}; + +extern S_small foo_small(); +extern S_large foo_large(); +extern void bar_small(S_small*); +extern void bar_large(S_large*); + +// Prevent mangling of function names. +extern "C" { + +void small_rvoed_unnamed_temporary_object() { +// CHECK-LABEL: define void @small_rvoed_unnamed_temporary_object +// CHECK: call void @llvm.lifetime.start +// CHECK: call void @_Z9foo_smallv +// CHECK: call void @llvm.lifetime.end +// CHECK: call void @llvm.lifetime.start +// CHECK: call void @_Z9foo_smallv +// CHECK: call void @llvm.lifetime.end + + foo_small(); + foo_small(); +} + +void large_rvoed_unnamed_temporary_object() { +// CHECK-LABEL: define void @large_rvoed_unnamed_temporary_object +// CHECK: call void @llvm.lifetime.start +// CHECK: call void @_Z9foo_largev +// CHECK: call void @llvm.lifetime.end +// CHECK: call void @llvm.lifetime.start +// CHECK: call void @_Z9foo_largev +// CHECK: call void @llvm.lifetime.end + + foo_large(); + foo_large(); +} + +void small_rvoed_named_temporary_object() { +// CHECK-LABEL: define void @small_rvoed_named_temporary_object +// CHECK: call void @llvm.lifetime.start +// CHECK: call void @_Z9foo_smallv +// CHECK: call void @llvm.lifetime.end +// CHECK: call void @llvm.lifetime.start +// CHECK: call void @_Z9foo_smallv +// CHECK: call void @llvm.lifetime.end + + { + S_small s = foo_small(); + } + { + S_small s = foo_small(); + } +} + +void large_rvoed_named_temporary_object() { +// CHECK-LABEL: define void @large_rvoed_named_temporary_object +// CHECK: call void @llvm.lifetime.start +// CHECK: call void @_Z9foo_largev +// CHECK: call void @llvm.lifetime.end +// CHECK: call void @llvm.lifetime.start +// CHECK: call void @_Z9foo_largev +// CHECK: call void @llvm.lifetime.end + + { + S_large s = foo_large(); + } + { + S_large s = foo_large(); + } +} + +void small_auto_object() { +// CHECK-LABEL: define void @small_auto_object +// CHECK: call void @llvm.lifetime.start +// CHECK: call void @_Z9bar_smallP7S_small +// CHECK: call void @llvm.lifetime.end +// CHECK: call void @llvm.lifetime.start +// CHECK: call void @_Z9bar_smallP7S_small +// CHECK: call void @llvm.lifetime.end + + { + S_small s; + bar_small(&s); + } + { + S_small s; + bar_small(&s); + } +} + +void large_auto_object() { +// CHECK-LABEL: define void @large_auto_object +// CHECK: call void @llvm.lifetime.start +// CHECK: call void @_Z9bar_largeP7S_large +// CHECK: call void @llvm.lifetime.end +// CHECK: call void @llvm.lifetime.start +// CHECK: call void @_Z9bar_largeP7S_large +// CHECK: call void @llvm.lifetime.end + + { + S_large s; + bar_large(&s); + } + { + S_large s; + bar_large(&s); + } +} + +int large_combiner_test(S_large s) { +// CHECK-LABEL: define i32 @large_combiner_test +// CHECK: [[T1:%.*]] = alloca %struct.Combiner +// CHECK: [[T2:%.*]] = alloca %struct.Combiner +// CHECK: [[T3:%.*]] = call %struct.Combiner* @_ZN8CombinerC1E7S_large(%struct.Combiner* [[T1]], [9 x i32] %s.coerce) +// CHECK: call void @_ZN8Combiner1fEv(%struct.Combiner* sret [[T2]], %struct.Combiner* [[T1]]) +// CHECK: [[T4:%.*]] = getelementptr inbounds %struct.Combiner, %struct.Combiner* [[T2]], i32 0, i32 0, i32 0, i32 0 +// CHECK: [[T5:%.*]] = load i32, i32* [[T4]] +// CHECK: ret i32 [[T5]] + + return Combiner(s).f().a.a[0]; +} + +} diff --git a/test/CodeGenCXX/x86_64-arguments-avx.cpp b/test/CodeGenCXX/x86_64-arguments-avx.cpp index 1b1c6420636e0..29e693451d128 100644 --- a/test/CodeGenCXX/x86_64-arguments-avx.cpp +++ b/test/CodeGenCXX/x86_64-arguments-avx.cpp @@ -13,3 +13,40 @@ PR22753 test(PR22753 x) { return x; } } + +namespace test2 { +typedef double __m128d __attribute__((__vector_size__(16))); +typedef float __m128 __attribute__((__vector_size__(16))); +typedef double __m256d __attribute__((__vector_size__(32))); +typedef float __m256 __attribute__((__vector_size__(32))); + +union U1 { + __m128 v1; + __m128d v2; +}; + +union UU1 { + union U1; + __m128d v3; +}; + +// CHECK: define <2 x double> @_ZN5test27PR23082ENS_3UU1E(<2 x double> +UU1 PR23082(UU1 x) { + return x; +} + +union U2 { + __m256 v1; + __m256d v2; +}; + +union UU2 { + union U2; + __m256d v3; +}; + +// CHECK: define <4 x double> @_ZN5test27PR23082ENS_3UU2E(<4 x double> +UU2 PR23082(UU2 x) { + return x; +} +} |
