[PATCH] D47090: Implement C++17 .
EricWF added a comment. I should add that this is the approach I've taken with `` with no complaints. Repository: rCXX libc++ https://reviews.llvm.org/D47090 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D47070: [CUDA] Upgrade linked bitcode to enable inlining
Hahnfeld added subscribers: chandlerc, ahatanak. Hahnfeld added a comment. Looks like this was added as a "temporary solution" in https://reviews.llvm.org/D8984. Meanwhile the attribute whitelist was merged half a year later (https://reviews.llvm.org/D7802), so maybe we can just get rid of comparing `target-cpu` and `target-features` entirely? Repository: rC Clang https://reviews.llvm.org/D47070 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D47090: Implement C++17 .
EricWF added a subscriber: dexonsmith. EricWF added a comment. Comment at: src/memory_resource.cpp:62 + +namespace { + We certainly don't want a different definition of the global resources in each TU. See below. Comment at: src/memory_resource.cpp:64 + +union ResourceInitHelper { + struct { This should go inside the library, so we're not emitting an initializer in each TU. Comment at: src/memory_resource.cpp:83 + +memory_resource * new_delete_resource() _NOEXCEPT { +return &res_init.resources.new_delete_res; I think the global resources should be in the unversioned namespace `std::pmr` instead of `std::__v::pmr`. Like new/delete and exceptions I suspect we only want one definition of these in any given program. I'm considering every function from here up to and including `set_default_resource`. @mclow.lists, @dexonsmith: what do you think? Comment at: src/memory_resource.cpp:147 + +template +struct __mr_holder { `_Tp` Comment at: src/memory_resource.cpp:149 +struct __mr_holder { +memory_resource *res; +void *ptr; `__res_` `__ptr_` `__size_` `__align_` Comment at: src/memory_resource.cpp:180 +struct __pool_resource_chunk { +size_t bytes; +size_t alignment; `__bytes_` `__alignment_` (or `__align_`) `__allocation_` `__next_` Repository: rCXX libc++ https://reviews.llvm.org/D47090 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r332804 - [Driver] Loosen test for LLVM findNearest
Author: modocache Date: Sat May 19 04:46:58 2018 New Revision: 332804 URL: http://llvm.org/viewvc/llvm-project?rev=332804&view=rev Log: [Driver] Loosen test for LLVM findNearest Summary: When https://reviews.llvm.org/D46776 landed to improve the behavior of `llvm::OptTable::findNearest`, a PS4 buildbot began failing due to an assertion that a suggestion "-debug-info-macro" should be provided for the unrecognized option `clang -cc1as -debug-info-macros`. All other buildbots succeeded in this check, and the PS4 buildbot succeeded in the other `findNearest` tests. Temporarily loosen this check in order to reland the `findNearest` change. Test Plan: check-clang Modified: cfe/trunk/test/Driver/unknown-arg.c Modified: cfe/trunk/test/Driver/unknown-arg.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/unknown-arg.c?rev=332804&r1=332803&r2=332804&view=diff == --- cfe/trunk/test/Driver/unknown-arg.c (original) +++ cfe/trunk/test/Driver/unknown-arg.c Sat May 19 04:46:58 2018 @@ -51,7 +51,7 @@ // SILENT-NOT: warning: // CC1AS-DID-YOU-MEAN: error: unknown argument '-hell', did you mean '-help'? // CC1AS-DID-YOU-MEAN: error: unknown argument '--version', did you mean '-version'? -// CC1AS-DID-YOU-MEAN: error: unknown argument '-debug-info-macros', did you mean '-debug-info-macro'? +// CC1AS-DID-YOU-MEAN: error: unknown argument '-debug-info-macros' // UNKNOWN-INTEGRATED: error: unknown integrated tool 'asphalt'. Valid tools include '-cc1' and '-cc1as'. // RUN: %clang -S %s -o %t.s -Wunknown-to-clang-option 2>&1 | FileCheck --check-prefix=IGNORED %s ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D47099: Disable casting of alloca for ActiveFlag
yaxunl added a comment. In https://reviews.llvm.org/D47099#1105493, @rjmccall wrote: > Maybe there should just be a method that makes a primitive alloca without the > casting, and then you can call that in CreateTempAlloca. In many cases we still need to call CreateTempAlloca with cast enabled, since we are not certain there is only load from it and store to it. Any time it is stored to another memory location or passed to another function (e.g. constructor/destructor), it needs to be a pointer to the language's default address space since the language sees it that way. https://reviews.llvm.org/D47099 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r332806 - [Driver] Temporarily remove test for LLVM findNearest
Author: modocache Date: Sat May 19 05:44:02 2018 New Revision: 332806 URL: http://llvm.org/viewvc/llvm-project?rev=332806&view=rev Log: [Driver] Temporarily remove test for LLVM findNearest Summary: This fixes a failure caused by the revert of https://reviews.llvm.org/rL332805. Modified: cfe/trunk/test/Driver/unknown-arg.c Modified: cfe/trunk/test/Driver/unknown-arg.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/unknown-arg.c?rev=332806&r1=332805&r2=332806&view=diff == --- cfe/trunk/test/Driver/unknown-arg.c (original) +++ cfe/trunk/test/Driver/unknown-arg.c Sat May 19 05:44:02 2018 @@ -51,7 +51,6 @@ // SILENT-NOT: warning: // CC1AS-DID-YOU-MEAN: error: unknown argument '-hell', did you mean '-help'? // CC1AS-DID-YOU-MEAN: error: unknown argument '--version', did you mean '-version'? -// CC1AS-DID-YOU-MEAN: error: unknown argument '-debug-info-macros' // UNKNOWN-INTEGRATED: error: unknown integrated tool 'asphalt'. Valid tools include '-cc1' and '-cc1as'. // RUN: %clang -S %s -o %t.s -Wunknown-to-clang-option 2>&1 | FileCheck --check-prefix=IGNORED %s ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[libcxx] r332811 - Implement deduction guides for forward_list
Author: marshall Date: Sat May 19 09:02:05 2018 New Revision: 332811 URL: http://llvm.org/viewvc/llvm-project?rev=332811&view=rev Log: Implement deduction guides for forward_list Added: libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.cons/deduct.fail.cpp libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.cons/deduct.pass.cpp Modified: libcxx/trunk/include/forward_list Modified: libcxx/trunk/include/forward_list URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/forward_list?rev=332811&r1=332810&r2=332811&view=diff == --- libcxx/trunk/include/forward_list (original) +++ libcxx/trunk/include/forward_list Sat May 19 09:02:05 2018 @@ -134,6 +134,11 @@ public: void reverse() noexcept; }; + +template ::value_type>> +forward_list(InputIterator, InputIterator, Allocator = Allocator()) +-> forward_list::value_type, Allocator>; // C++17 + template bool operator==(const forward_list& x, const forward_list& y); @@ -845,6 +850,23 @@ private: __sort(__node_pointer __f, difference_type __sz, _Compare& __comp); }; + +#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES +template::value_type>, + class = typename enable_if<__is_allocator<_Alloc>::value, void>::type + > +forward_list(_InputIterator, _InputIterator) + -> forward_list::value_type, _Alloc>; + +template::value, void>::type + > +forward_list(_InputIterator, _InputIterator, _Alloc) + -> forward_list::value_type, _Alloc>; +#endif + template inline forward_list<_Tp, _Alloc>::forward_list(const allocator_type& __a) Added: libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.cons/deduct.fail.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.cons/deduct.fail.cpp?rev=332811&view=auto == --- libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.cons/deduct.fail.cpp (added) +++ libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.cons/deduct.fail.cpp Sat May 19 09:02:05 2018 @@ -0,0 +1,42 @@ +//===--===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===--===// + +// +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: libcpp-no-deduction-guides + + +// template ::value_type>> +//forward_list(InputIterator, InputIterator, Allocator = Allocator()) +//-> forward_list::value_type, Allocator>; +// + + +#include +#include +#include +#include +#include // INT_MAX + +struct A {}; + +int main() +{ +// Test the explicit deduction guides + +// Test the implicit deduction guides +{ +// forward_list (allocator &) +std::forward_list fwl((std::allocator())); // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'forward_list'}} +// Note: The extra parens are necessary, since otherwise clang decides it is a function declaration. +// Also, we can't use {} instead of parens, because that constructs a +// forward_list, allocator>> +} + +} Added: libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.cons/deduct.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.cons/deduct.pass.cpp?rev=332811&view=auto == --- libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.cons/deduct.pass.cpp (added) +++ libcxx/trunk/test/std/containers/sequences/forwardlist/forwardlist.cons/deduct.pass.cpp Sat May 19 09:02:05 2018 @@ -0,0 +1,103 @@ +//===--===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===--===// + +// +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: libcpp-no-deduction-guides + + +// template ::value_type>> +//deque(InputIterator, InputIterator, Allocator = Allocator()) +//-> deque::value_type, Allocator>; +// + + +#include +#include +#include +#include +#include // INT_MAX + +#include "test_macros.h" +#include "test_iterators.h" +#include "test_allocator.h" + +struct A {}; + +int main() +{ + +// Test the explicit deduction guides +{ +const int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; +std::forward_list fwl(std::begi
[PATCH] D46845: [libcxx][c++17] P0083R5: Splicing Maps and Sets
erik.pilkington added a comment. In https://reviews.llvm.org/D46845#1098634, @rsmith wrote: > One way we could deal with this is by adding an attribute to the compiler to > indicate "the const is a lie", that we can apply to `std::pair::first`, with > the semantics being that a top-level `const` is ignored when determining the > "real" type of the member (and so mutating the member after a `const_cast` > has defined behavior). This would apply to //all// `std::pair`s, not just > the `node_handle` case, but in practice we don't optimize on the basis of a > member being declared `const` *anyway*, so this isn't such a big deal right > now. Would you mind elaborating on this? If we don't optimize on a member being const, then what should this attribute actually do? The only thing I can think of is making a field with type `const T` with the attribute claim it's a `T` to TBAA, but that would be a no-op because loads and stores through those types are compatible anyways. In https://reviews.llvm.org/D46845#1098634, @rsmith wrote: > Yet another possibility would be to only ever access the `key` field through > a type annotated with `__attribute__((may_alias))`, and then launder the node > pointer when we're ready to insert it back into the container (to "pick up" > the new value of the const member). That's formally breaking the rules (a > `launder` isn't enough, because we didn't actually create a new object, and > in any case we still mutated the value of a `const` subobject), but it'll > probably work fine across compilers that support the attribute. What about instead of type-punning between pair and pair (with may_alias) we just did a const_cast in key, and launder the pair when finished? Because loads and stores to `const K` and `K` are already assumed to alias each other, we should be able to omit the may_alias attribute (right?). Would that be enough to placate the compiler? If it is, then I think we should just do this and avoid adding another attribute to clang. I'll upload a patch with this to show what I mean. Thanks! Erik https://reviews.llvm.org/D46845 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D47090: Implement C++17 .
Quuxplusone added inline comments. Comment at: include/__memory_resource_base:196 + typename __uses_alloc_ctor< + _T1, polymorphic_allocator&, _Args1... + >::type() >> (B) It's got different semantics around uses-allocator construction because >> of https://wg21.link/lwg2969 > Issue resolutions should probably be applied to the experimental versions as > well. Okay, I can roll with that. I'll create a new patch that modifies ``'s uses-allocator parts per LWG2969 (and my followup DR), without any other diffs. Should `` continue caring about `std::experimental::erased_type`, which was in LFTS and LFTSv2 but did not make it into C++17? My kneejerk reaction is "yes". (And at the end of this process, when we copy `` into ``, should `` care about `erased_type`? My kneejerk reaction is "no".) Comment at: src/memory_resource.cpp:62 + +namespace { + EricWF wrote: > We certainly don't want a different definition of the global resources in > each TU. See below. @EricWF: I think all of your comments in this file are the result of misreading "src/memory_resource.cpp" as "include/memory_resource". Or else I *totally* don't understand the current directory organization and you're going to have to instruct me. :) Repository: rCXX libc++ https://reviews.llvm.org/D47090 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D47090: Implement C++17 .
EricWF added inline comments. Comment at: src/memory_resource.cpp:62 + +namespace { + Quuxplusone wrote: > EricWF wrote: > > We certainly don't want a different definition of the global resources in > > each TU. See below. > @EricWF: I think all of your comments in this file are the result of > misreading "src/memory_resource.cpp" as "include/memory_resource". Or else I > *totally* don't understand the current directory organization and you're > going to have to instruct me. :) > Woops. I feel dumb now. Repository: rCXX libc++ https://reviews.llvm.org/D47090 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D47108: Add -fforce-emit-vtable
Prazek created this revision. Prazek added reviewers: rjmccall, rsmith, amharc, kuhar. Herald added a subscriber: llvm-commits. In many cases we can't devirtualize because definition of vtable is not present. Most of the time it is caused by inline virtual function not beeing emitted. Forcing emitting of vtable adds a reference of these inline virtual functions Repository: rL LLVM https://reviews.llvm.org/D47108 Files: clang/docs/ClangCommandLineReference.rst clang/docs/UsersManual.rst clang/include/clang/Driver/Options.td clang/include/clang/Frontend/CodeGenOptions.def clang/lib/CodeGen/ItaniumCXXABI.cpp clang/lib/Driver/ToolChains/Clang.cpp clang/lib/Frontend/CompilerInvocation.cpp clang/test/CodeGenCXX/vtable-available-externally.cpp clang/test/CodeGenCXX/vtable-linkage.cpp Index: clang/test/CodeGenCXX/vtable-linkage.cpp === --- clang/test/CodeGenCXX/vtable-linkage.cpp +++ clang/test/CodeGenCXX/vtable-linkage.cpp @@ -1,11 +1,13 @@ // RUN: %clang_cc1 %s -triple=x86_64-pc-linux -emit-llvm -o %t // RUN: %clang_cc1 %s -triple=x86_64-pc-linux -emit-llvm -std=c++03 -o %t.03 // RUN: %clang_cc1 %s -triple=x86_64-pc-linux -emit-llvm -std=c++11 -o %t.11 +// RUN: %clang_cc1 %s -triple=x86_64-pc-linux -emit-llvm -std=c++11 -o %t.vtables -fforce-emit-vtables -O3 // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -disable-llvm-passes -O3 -emit-llvm -o %t.opt // RUN: FileCheck %s < %t // RUN: FileCheck %s < %t.03 // RUN: FileCheck %s < %t.11 // RUN: FileCheck --check-prefix=CHECK-OPT %s < %t.opt +// RUN: FileCheck --check-prefix=CHECK-OPT %s < %t.vtables namespace { struct A { Index: clang/test/CodeGenCXX/vtable-available-externally.cpp === --- clang/test/CodeGenCXX/vtable-available-externally.cpp +++ clang/test/CodeGenCXX/vtable-available-externally.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -emit-llvm -o %t // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.opt +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.vtable -fforce-emit-vtables // RUN: FileCheck --check-prefix=CHECK-TEST1 %s < %t // RUN: FileCheck --check-prefix=CHECK-TEST2 %s < %t // RUN: FileCheck --check-prefix=CHECK-TEST5 %s < %t @@ -13,10 +14,13 @@ // RUN: FileCheck --check-prefix=CHECK-TEST15 %s < %t.opt // RUN: FileCheck --check-prefix=CHECK-TEST16 %s < %t.opt // RUN: FileCheck --check-prefix=CHECK-TEST17 %s < %t.opt +// RUN: FileCheck --check-prefix=CHECK-FORCE-EMIT %s < %t.vtable + #include // CHECK-TEST1: @_ZTVN5Test11AE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN5Test11AE = available_externally unnamed_addr constant namespace Test1 { struct A { @@ -213,14 +217,16 @@ // because A's key function is defined here, vtable is generated in this TU // CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101AE = unnamed_addr constant struct A { virtual void foo(); virtual void bar(); }; void A::foo() {} // Because key function is inline we will generate vtable as linkonce_odr. // CHECK-TEST10-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant struct D : A { void bar(); }; @@ -237,14 +243,17 @@ // can't guarantee that we will be able to refer to bar from name // so (at the moment) we can't emit vtable available_externally. // CHECK-TEST10-DAG: @_ZTVN6Test101CE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101CE = available_externally unnamed_addr constant struct C : A { void bar() {} // defined in body - not key function virtual inline void gar(); // inline in body - not key function virtual void car(); }; // no key function, vtable will be generated everywhere it will be used // CHECK-TEST10-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant + struct E : A {}; void g(A& a) { @@ -298,11 +307,13 @@ namespace Test12 { // CHECK-TEST12: @_ZTVN6Test121AE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121AE = available_externally unnamed_addr constant struct A { virtual void foo(); virtual ~A() {} }; // CHECK-TEST12: @_ZTVN6Test121BE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121BE = available_externally unnamed_addr constant struct B : A { void foo(); }; @@ -319,6 +330,9 @@ // CHECK-TEST13-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant // CHECK-TEST13-DAG: @_ZTVN6Test131BE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant +// CHECK-FORC
[PATCH] D47108: Add -fforce-emit-vtable
Prazek updated this revision to Diff 147672. Prazek added a comment. Add release note Repository: rL LLVM https://reviews.llvm.org/D47108 Files: clang/docs/ClangCommandLineReference.rst clang/docs/ReleaseNotes.rst clang/docs/UsersManual.rst clang/include/clang/Driver/Options.td clang/include/clang/Frontend/CodeGenOptions.def clang/lib/CodeGen/ItaniumCXXABI.cpp clang/lib/Driver/ToolChains/Clang.cpp clang/lib/Frontend/CompilerInvocation.cpp clang/test/CodeGenCXX/vtable-available-externally.cpp clang/test/CodeGenCXX/vtable-linkage.cpp Index: clang/test/CodeGenCXX/vtable-linkage.cpp === --- clang/test/CodeGenCXX/vtable-linkage.cpp +++ clang/test/CodeGenCXX/vtable-linkage.cpp @@ -7,6 +7,7 @@ // RUN: FileCheck %s < %t.11 // RUN: FileCheck --check-prefix=CHECK-OPT %s < %t.opt + namespace { struct A { virtual void f() { } Index: clang/test/CodeGenCXX/vtable-available-externally.cpp === --- clang/test/CodeGenCXX/vtable-available-externally.cpp +++ clang/test/CodeGenCXX/vtable-available-externally.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -emit-llvm -o %t // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.opt +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.vtable -fforce-emit-vtables // RUN: FileCheck --check-prefix=CHECK-TEST1 %s < %t // RUN: FileCheck --check-prefix=CHECK-TEST2 %s < %t // RUN: FileCheck --check-prefix=CHECK-TEST5 %s < %t @@ -13,10 +14,13 @@ // RUN: FileCheck --check-prefix=CHECK-TEST15 %s < %t.opt // RUN: FileCheck --check-prefix=CHECK-TEST16 %s < %t.opt // RUN: FileCheck --check-prefix=CHECK-TEST17 %s < %t.opt +// RUN: FileCheck --check-prefix=CHECK-FORCE-EMIT %s < %t.vtable + #include // CHECK-TEST1: @_ZTVN5Test11AE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN5Test11AE = available_externally unnamed_addr constant namespace Test1 { struct A { @@ -213,14 +217,16 @@ // because A's key function is defined here, vtable is generated in this TU // CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101AE = unnamed_addr constant struct A { virtual void foo(); virtual void bar(); }; void A::foo() {} // Because key function is inline we will generate vtable as linkonce_odr. // CHECK-TEST10-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant struct D : A { void bar(); }; @@ -237,14 +243,17 @@ // can't guarantee that we will be able to refer to bar from name // so (at the moment) we can't emit vtable available_externally. // CHECK-TEST10-DAG: @_ZTVN6Test101CE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101CE = available_externally unnamed_addr constant struct C : A { void bar() {} // defined in body - not key function virtual inline void gar(); // inline in body - not key function virtual void car(); }; // no key function, vtable will be generated everywhere it will be used // CHECK-TEST10-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant + struct E : A {}; void g(A& a) { @@ -298,11 +307,13 @@ namespace Test12 { // CHECK-TEST12: @_ZTVN6Test121AE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121AE = available_externally unnamed_addr constant struct A { virtual void foo(); virtual ~A() {} }; // CHECK-TEST12: @_ZTVN6Test121BE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121BE = available_externally unnamed_addr constant struct B : A { void foo(); }; @@ -319,6 +330,9 @@ // CHECK-TEST13-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant // CHECK-TEST13-DAG: @_ZTVN6Test131BE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131BE = available_externally unnamed_addr constant + struct A { virtual ~A(); }; @@ -371,6 +385,8 @@ // generate available_externally vtable for it. // CHECK-TEST16-DAG: @_ZTVN6Test161SE = external unnamed_addr constant // CHECK-TEST16-DAG: @_ZTVN6Test162S2E = available_externally +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test161SE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test162S2E = available_externally struct S { __attribute__((visibility("hidden"))) virtual void doStuff(); @@ -395,6 +411,10 @@ // This test checks if we emit vtables opportunistically. // CHECK-TEST17-DAG: @_ZTVN6Test171AE = available_externally // CHECK-TEST17-DAG: @_ZTVN6Test171BE = external +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test17
[PATCH] D47108: Add -fforce-emit-vtable
Prazek updated this revision to Diff 147673. Prazek added a comment. remove empty line Repository: rL LLVM https://reviews.llvm.org/D47108 Files: clang/docs/ClangCommandLineReference.rst clang/docs/ReleaseNotes.rst clang/docs/UsersManual.rst clang/include/clang/Driver/Options.td clang/include/clang/Frontend/CodeGenOptions.def clang/lib/CodeGen/ItaniumCXXABI.cpp clang/lib/Driver/ToolChains/Clang.cpp clang/lib/Frontend/CompilerInvocation.cpp clang/test/CodeGenCXX/vtable-available-externally.cpp Index: clang/test/CodeGenCXX/vtable-available-externally.cpp === --- clang/test/CodeGenCXX/vtable-available-externally.cpp +++ clang/test/CodeGenCXX/vtable-available-externally.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -emit-llvm -o %t // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.opt +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.vtable -fforce-emit-vtables // RUN: FileCheck --check-prefix=CHECK-TEST1 %s < %t // RUN: FileCheck --check-prefix=CHECK-TEST2 %s < %t // RUN: FileCheck --check-prefix=CHECK-TEST5 %s < %t @@ -13,10 +14,13 @@ // RUN: FileCheck --check-prefix=CHECK-TEST15 %s < %t.opt // RUN: FileCheck --check-prefix=CHECK-TEST16 %s < %t.opt // RUN: FileCheck --check-prefix=CHECK-TEST17 %s < %t.opt +// RUN: FileCheck --check-prefix=CHECK-FORCE-EMIT %s < %t.vtable + #include // CHECK-TEST1: @_ZTVN5Test11AE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN5Test11AE = available_externally unnamed_addr constant namespace Test1 { struct A { @@ -213,14 +217,16 @@ // because A's key function is defined here, vtable is generated in this TU // CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101AE = unnamed_addr constant struct A { virtual void foo(); virtual void bar(); }; void A::foo() {} // Because key function is inline we will generate vtable as linkonce_odr. // CHECK-TEST10-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant struct D : A { void bar(); }; @@ -237,14 +243,17 @@ // can't guarantee that we will be able to refer to bar from name // so (at the moment) we can't emit vtable available_externally. // CHECK-TEST10-DAG: @_ZTVN6Test101CE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101CE = available_externally unnamed_addr constant struct C : A { void bar() {} // defined in body - not key function virtual inline void gar(); // inline in body - not key function virtual void car(); }; // no key function, vtable will be generated everywhere it will be used // CHECK-TEST10-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant + struct E : A {}; void g(A& a) { @@ -298,11 +307,13 @@ namespace Test12 { // CHECK-TEST12: @_ZTVN6Test121AE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121AE = available_externally unnamed_addr constant struct A { virtual void foo(); virtual ~A() {} }; // CHECK-TEST12: @_ZTVN6Test121BE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121BE = available_externally unnamed_addr constant struct B : A { void foo(); }; @@ -319,6 +330,9 @@ // CHECK-TEST13-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant // CHECK-TEST13-DAG: @_ZTVN6Test131BE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131BE = available_externally unnamed_addr constant + struct A { virtual ~A(); }; @@ -371,6 +385,8 @@ // generate available_externally vtable for it. // CHECK-TEST16-DAG: @_ZTVN6Test161SE = external unnamed_addr constant // CHECK-TEST16-DAG: @_ZTVN6Test162S2E = available_externally +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test161SE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test162S2E = available_externally struct S { __attribute__((visibility("hidden"))) virtual void doStuff(); @@ -395,6 +411,10 @@ // This test checks if we emit vtables opportunistically. // CHECK-TEST17-DAG: @_ZTVN6Test171AE = available_externally // CHECK-TEST17-DAG: @_ZTVN6Test171BE = external +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171AE = available_externally +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171BE = available_externally +// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD1Ev( +// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD0Ev( struct A { virtual void key(); Index: clang/lib/Frontend/CompilerInvocation.cpp === --- clang/lib/Fronte
[PATCH] D47108: Add -fforce-emit-vtable
Prazek updated this revision to Diff 147675. Prazek added a comment. Fixed comment Repository: rL LLVM https://reviews.llvm.org/D47108 Files: clang/docs/ClangCommandLineReference.rst clang/docs/ReleaseNotes.rst clang/docs/UsersManual.rst clang/include/clang/Driver/Options.td clang/include/clang/Frontend/CodeGenOptions.def clang/lib/CodeGen/ItaniumCXXABI.cpp clang/lib/Driver/ToolChains/Clang.cpp clang/lib/Frontend/CompilerInvocation.cpp clang/test/CodeGenCXX/vtable-available-externally.cpp Index: clang/test/CodeGenCXX/vtable-available-externally.cpp === --- clang/test/CodeGenCXX/vtable-available-externally.cpp +++ clang/test/CodeGenCXX/vtable-available-externally.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -emit-llvm -o %t // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.opt +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.vtable -fforce-emit-vtables // RUN: FileCheck --check-prefix=CHECK-TEST1 %s < %t // RUN: FileCheck --check-prefix=CHECK-TEST2 %s < %t // RUN: FileCheck --check-prefix=CHECK-TEST5 %s < %t @@ -13,10 +14,13 @@ // RUN: FileCheck --check-prefix=CHECK-TEST15 %s < %t.opt // RUN: FileCheck --check-prefix=CHECK-TEST16 %s < %t.opt // RUN: FileCheck --check-prefix=CHECK-TEST17 %s < %t.opt +// RUN: FileCheck --check-prefix=CHECK-FORCE-EMIT %s < %t.vtable + #include // CHECK-TEST1: @_ZTVN5Test11AE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN5Test11AE = available_externally unnamed_addr constant namespace Test1 { struct A { @@ -213,14 +217,16 @@ // because A's key function is defined here, vtable is generated in this TU // CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101AE = unnamed_addr constant struct A { virtual void foo(); virtual void bar(); }; void A::foo() {} // Because key function is inline we will generate vtable as linkonce_odr. // CHECK-TEST10-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant struct D : A { void bar(); }; @@ -237,14 +243,17 @@ // can't guarantee that we will be able to refer to bar from name // so (at the moment) we can't emit vtable available_externally. // CHECK-TEST10-DAG: @_ZTVN6Test101CE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101CE = available_externally unnamed_addr constant struct C : A { void bar() {} // defined in body - not key function virtual inline void gar(); // inline in body - not key function virtual void car(); }; // no key function, vtable will be generated everywhere it will be used // CHECK-TEST10-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant + struct E : A {}; void g(A& a) { @@ -298,11 +307,13 @@ namespace Test12 { // CHECK-TEST12: @_ZTVN6Test121AE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121AE = available_externally unnamed_addr constant struct A { virtual void foo(); virtual ~A() {} }; // CHECK-TEST12: @_ZTVN6Test121BE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121BE = available_externally unnamed_addr constant struct B : A { void foo(); }; @@ -319,6 +330,9 @@ // CHECK-TEST13-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant // CHECK-TEST13-DAG: @_ZTVN6Test131BE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131BE = available_externally unnamed_addr constant + struct A { virtual ~A(); }; @@ -371,6 +385,8 @@ // generate available_externally vtable for it. // CHECK-TEST16-DAG: @_ZTVN6Test161SE = external unnamed_addr constant // CHECK-TEST16-DAG: @_ZTVN6Test162S2E = available_externally +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test161SE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test162S2E = available_externally struct S { __attribute__((visibility("hidden"))) virtual void doStuff(); @@ -395,6 +411,10 @@ // This test checks if we emit vtables opportunistically. // CHECK-TEST17-DAG: @_ZTVN6Test171AE = available_externally // CHECK-TEST17-DAG: @_ZTVN6Test171BE = external +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171AE = available_externally +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171BE = available_externally +// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD1Ev( +// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD0Ev( struct A { virtual void key(); Index: clang/lib/Frontend/CompilerInvocation.cpp === --- clang/lib/Frontend/C
[PATCH] D47109: LWG 2969 "polymorphic_allocator::construct() shouldn't pass resource()"
Quuxplusone created this revision. Quuxplusone added a reviewer: EricWF. Herald added a subscriber: cfe-commits. In the TS, `uses_allocator` construction for `pair` tried to use an allocator type of `memory_resource*`, which is incorrect because `memory_resource*` is not an allocator type. LWG 2969 fixed it to use `polymorphic_allocator` as the allocator type instead. https://wg21.link/lwg2969 (https://reviews.llvm.org/D47090 included this in ``; at Eric's request, I've split this out into its own patch applied to the existing `` instead.) Repository: rCXX libc++ https://reviews.llvm.org/D47109 Files: include/experimental/memory_resource test/std/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/construct_pair_const_lvalue_pair.pass.cpp test/std/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/construct_pair_rvalue.pass.cpp test/std/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/construct_pair_values.pass.cpp test/std/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/construct_piecewise_pair.pass.cpp test/std/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/construct_piecewise_pair_evil.pass.cpp test/std/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/construct_types.pass.cpp test/support/test_memory_resource.hpp Index: test/support/test_memory_resource.hpp === --- test/support/test_memory_resource.hpp +++ test/support/test_memory_resource.hpp @@ -28,7 +28,7 @@ // because it can't include template <> struct TransformErasedTypeAlloc { - using type = std::experimental::pmr::memory_resource*; + using type = std::experimental::pmr::polymorphic_allocator; }; template Index: test/std/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/construct_types.pass.cpp === --- test/std/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/construct_types.pass.cpp +++ test/std/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/construct_types.pass.cpp @@ -126,6 +126,39 @@ } } +template +void test_pmr_not_uses_alloc(Args&&... args) +{ +TestResource R(12435); +ex::memory_resource* M = &R; +{ +// NotUsesAllocator provides valid signatures for each uses-allocator +// construction but does not supply the required allocator_type typedef. +// Test that we can call these constructors manually without +// polymorphic_allocator interfering. +using T = NotUsesAllocator; +assert(doTestUsesAllocV0(std::forward(args)...)); +assert((doTestUsesAllocV1(M, std::forward(args)...))); +assert((doTestUsesAllocV2(M, std::forward(args)...))); +} +{ +// Test T(std::allocator_arg_t, Alloc const&, Args...) construction +using T = UsesAllocatorV1; +assert((doTest(UA_None, std::forward(args)...))); +} +{ +// Test T(Args..., Alloc const&) construction +using T = UsesAllocatorV2; +assert((doTest(UA_None, std::forward(args)...))); +} +{ +// Test that T(std::allocator_arg_t, Alloc const&, Args...) construction +// is preferred when T(Args..., Alloc const&) is also available. +using T = UsesAllocatorV3; +assert((doTest(UA_None, std::forward(args)...))); +} +} + // Test that polymorphic_allocator does not prevent us from manually // doing non-pmr uses-allocator construction. template @@ -167,16 +200,16 @@ const int cvalue = 43; { test_pmr_uses_alloc(); -test_pmr_uses_alloc(); +test_pmr_not_uses_alloc(); test_pmr_uses_alloc(); test_pmr_uses_alloc(value); -test_pmr_uses_alloc(value); +test_pmr_not_uses_alloc(value); test_pmr_uses_alloc(value); test_pmr_uses_alloc(cvalue); -test_pmr_uses_alloc(cvalue); +test_pmr_not_uses_alloc(cvalue); test_pmr_uses_alloc(cvalue); test_pmr_uses_alloc(cvalue, std::move(value)); -test_pmr_uses_alloc(cvalue, std::move(value)); +test_pmr_not_uses_alloc(cvalue, std::move(value)); test_pmr_uses_alloc(cvalue, std::move(value)); } { Index: test/std/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/construct_piecewise_pair_evil.pass.cpp === --- /dev/null +++ test/std/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/construct_piecewise_pair_evil.pass.cpp @@ -0,0 +1,141 @@ +//===
[PATCH] D47109: LWG 2969 "polymorphic_allocator::construct() shouldn't pass resource()"
Quuxplusone updated this revision to Diff 147676. Quuxplusone added a comment. Herald added a subscriber: christof. Fix two more tests hiding in test/libcxx/, and give -U999 context. Repository: rCXX libc++ https://reviews.llvm.org/D47109 Files: include/experimental/memory_resource test/libcxx/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/construct_piecewise_pair.pass.cpp test/std/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/construct_pair_const_lvalue_pair.pass.cpp test/std/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/construct_pair_rvalue.pass.cpp test/std/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/construct_pair_values.pass.cpp test/std/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/construct_piecewise_pair.pass.cpp test/std/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/construct_piecewise_pair_evil.pass.cpp test/std/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/construct_types.pass.cpp test/support/test_memory_resource.hpp Index: test/support/test_memory_resource.hpp === --- test/support/test_memory_resource.hpp +++ test/support/test_memory_resource.hpp @@ -28,7 +28,7 @@ // because it can't include template <> struct TransformErasedTypeAlloc { - using type = std::experimental::pmr::memory_resource*; + using type = std::experimental::pmr::polymorphic_allocator; }; template Index: test/std/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/construct_types.pass.cpp === --- test/std/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/construct_types.pass.cpp +++ test/std/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/construct_types.pass.cpp @@ -126,6 +126,39 @@ } } +template +void test_pmr_not_uses_alloc(Args&&... args) +{ +TestResource R(12435); +ex::memory_resource* M = &R; +{ +// NotUsesAllocator provides valid signatures for each uses-allocator +// construction but does not supply the required allocator_type typedef. +// Test that we can call these constructors manually without +// polymorphic_allocator interfering. +using T = NotUsesAllocator; +assert(doTestUsesAllocV0(std::forward(args)...)); +assert((doTestUsesAllocV1(M, std::forward(args)...))); +assert((doTestUsesAllocV2(M, std::forward(args)...))); +} +{ +// Test T(std::allocator_arg_t, Alloc const&, Args...) construction +using T = UsesAllocatorV1; +assert((doTest(UA_None, std::forward(args)...))); +} +{ +// Test T(Args..., Alloc const&) construction +using T = UsesAllocatorV2; +assert((doTest(UA_None, std::forward(args)...))); +} +{ +// Test that T(std::allocator_arg_t, Alloc const&, Args...) construction +// is preferred when T(Args..., Alloc const&) is also available. +using T = UsesAllocatorV3; +assert((doTest(UA_None, std::forward(args)...))); +} +} + // Test that polymorphic_allocator does not prevent us from manually // doing non-pmr uses-allocator construction. template @@ -167,16 +200,16 @@ const int cvalue = 43; { test_pmr_uses_alloc(); -test_pmr_uses_alloc(); +test_pmr_not_uses_alloc(); test_pmr_uses_alloc(); test_pmr_uses_alloc(value); -test_pmr_uses_alloc(value); +test_pmr_not_uses_alloc(value); test_pmr_uses_alloc(value); test_pmr_uses_alloc(cvalue); -test_pmr_uses_alloc(cvalue); +test_pmr_not_uses_alloc(cvalue); test_pmr_uses_alloc(cvalue); test_pmr_uses_alloc(cvalue, std::move(value)); -test_pmr_uses_alloc(cvalue, std::move(value)); +test_pmr_not_uses_alloc(cvalue, std::move(value)); test_pmr_uses_alloc(cvalue, std::move(value)); } { Index: test/std/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/construct_piecewise_pair_evil.pass.cpp === --- /dev/null +++ test/std/experimental/memory/memory.polymorphic.allocator.class/memory.polymorphic.allocator.mem/construct_piecewise_pair_evil.pass.cpp @@ -0,0 +1,141 @@ +//===--===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===--
[PATCH] D47109: LWG 2969 "polymorphic_allocator::construct() shouldn't pass resource()"
EricWF accepted this revision. EricWF added a comment. This revision is now accepted and ready to land. This LGTM. Let's land it and see if anybody complains. Repository: rCXX libc++ https://reviews.llvm.org/D47109 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D47109: LWG 2969 "polymorphic_allocator::construct() shouldn't pass resource()"
Quuxplusone added a comment. In https://reviews.llvm.org/D47109#1105680, @EricWF wrote: > This LGTM. Let's land it and see if anybody complains. Sounds good to me. I don't have commit privs so could you land it for me? (Besides, I'm happy for you to get the blame if it *does* break someone's code, as I suspect it might. ;)) Repository: rCXX libc++ https://reviews.llvm.org/D47109 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D46806: Remove unused code from __functional_base. NFC.
Quuxplusone updated this revision to Diff 147677. Quuxplusone added a comment. @EricWF: would you mind landing these two drive-by fixes while you're at it? Repository: rCXX libc++ https://reviews.llvm.org/D46806 Files: include/__functional_base include/experimental/memory_resource Index: include/experimental/memory_resource === --- include/experimental/memory_resource +++ include/experimental/memory_resource @@ -96,7 +96,7 @@ } // 8.5, memory.resource -class _LIBCPP_TEMPLATE_VIS memory_resource +class _LIBCPP_TYPE_VIS memory_resource { static const size_t __max_align = alignof(max_align_t); Index: include/__functional_base === --- include/__functional_base +++ include/__functional_base @@ -646,16 +646,6 @@ new (__storage) _Tp (_VSTD::forward<_Args>(__args)..., __a); } -// FIXME: Theis should have a version which takes a non-const alloc. -template -inline _LIBCPP_INLINE_VISIBILITY -void __user_alloc_construct (_Tp *__storage, const _Allocator &__a, _Args &&... __args) -{ -__user_alloc_construct_impl( - __uses_alloc_ctor<_Tp, _Allocator>(), - __storage, __a, _VSTD::forward<_Args>(__args)... -); -} #endif // _LIBCPP_CXX03_LANG _LIBCPP_END_NAMESPACE_STD Index: include/experimental/memory_resource === --- include/experimental/memory_resource +++ include/experimental/memory_resource @@ -96,7 +96,7 @@ } // 8.5, memory.resource -class _LIBCPP_TEMPLATE_VIS memory_resource +class _LIBCPP_TYPE_VIS memory_resource { static const size_t __max_align = alignof(max_align_t); Index: include/__functional_base === --- include/__functional_base +++ include/__functional_base @@ -646,16 +646,6 @@ new (__storage) _Tp (_VSTD::forward<_Args>(__args)..., __a); } -// FIXME: Theis should have a version which takes a non-const alloc. -template -inline _LIBCPP_INLINE_VISIBILITY -void __user_alloc_construct (_Tp *__storage, const _Allocator &__a, _Args &&... __args) -{ -__user_alloc_construct_impl( - __uses_alloc_ctor<_Tp, _Allocator>(), - __storage, __a, _VSTD::forward<_Args>(__args)... -); -} #endif // _LIBCPP_CXX03_LANG _LIBCPP_END_NAMESPACE_STD ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D46806: Remove unused code from __functional_base. NFC.
Quuxplusone added inline comments. Comment at: include/experimental/memory_resource:99 // 8.5, memory.resource -class _LIBCPP_TEMPLATE_VIS memory_resource +class _LIBCPP_TYPE_VIS memory_resource { ...although maybe I don't understand the rules here. For example, I see `allocator_arg_t` and `monostate` are both marked `_LIBCPP_TEMPLATE_VIS` as well, even though they're not templates. Repository: rCXX libc++ https://reviews.llvm.org/D46806 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D47108: Add -fforce-emit-vtable
Prazek updated this revision to Diff 147679. Prazek added a comment. Fixed flag passing Repository: rL LLVM https://reviews.llvm.org/D47108 Files: clang/docs/ClangCommandLineReference.rst clang/docs/ReleaseNotes.rst clang/docs/UsersManual.rst clang/include/clang/Driver/Options.td clang/include/clang/Frontend/CodeGenOptions.def clang/lib/CodeGen/ItaniumCXXABI.cpp clang/lib/Driver/ToolChains/Clang.cpp clang/lib/Frontend/CompilerInvocation.cpp clang/test/CodeGenCXX/vtable-available-externally.cpp Index: clang/test/CodeGenCXX/vtable-available-externally.cpp === --- clang/test/CodeGenCXX/vtable-available-externally.cpp +++ clang/test/CodeGenCXX/vtable-available-externally.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -emit-llvm -o %t // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.opt +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.vtable -fforce-emit-vtables // RUN: FileCheck --check-prefix=CHECK-TEST1 %s < %t // RUN: FileCheck --check-prefix=CHECK-TEST2 %s < %t // RUN: FileCheck --check-prefix=CHECK-TEST5 %s < %t @@ -13,10 +14,13 @@ // RUN: FileCheck --check-prefix=CHECK-TEST15 %s < %t.opt // RUN: FileCheck --check-prefix=CHECK-TEST16 %s < %t.opt // RUN: FileCheck --check-prefix=CHECK-TEST17 %s < %t.opt +// RUN: FileCheck --check-prefix=CHECK-FORCE-EMIT %s < %t.vtable + #include // CHECK-TEST1: @_ZTVN5Test11AE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN5Test11AE = available_externally unnamed_addr constant namespace Test1 { struct A { @@ -213,14 +217,16 @@ // because A's key function is defined here, vtable is generated in this TU // CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101AE = unnamed_addr constant struct A { virtual void foo(); virtual void bar(); }; void A::foo() {} // Because key function is inline we will generate vtable as linkonce_odr. // CHECK-TEST10-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant struct D : A { void bar(); }; @@ -237,14 +243,17 @@ // can't guarantee that we will be able to refer to bar from name // so (at the moment) we can't emit vtable available_externally. // CHECK-TEST10-DAG: @_ZTVN6Test101CE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101CE = available_externally unnamed_addr constant struct C : A { void bar() {} // defined in body - not key function virtual inline void gar(); // inline in body - not key function virtual void car(); }; // no key function, vtable will be generated everywhere it will be used // CHECK-TEST10-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant + struct E : A {}; void g(A& a) { @@ -298,11 +307,13 @@ namespace Test12 { // CHECK-TEST12: @_ZTVN6Test121AE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121AE = available_externally unnamed_addr constant struct A { virtual void foo(); virtual ~A() {} }; // CHECK-TEST12: @_ZTVN6Test121BE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121BE = available_externally unnamed_addr constant struct B : A { void foo(); }; @@ -319,6 +330,9 @@ // CHECK-TEST13-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant // CHECK-TEST13-DAG: @_ZTVN6Test131BE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131BE = available_externally unnamed_addr constant + struct A { virtual ~A(); }; @@ -371,6 +385,8 @@ // generate available_externally vtable for it. // CHECK-TEST16-DAG: @_ZTVN6Test161SE = external unnamed_addr constant // CHECK-TEST16-DAG: @_ZTVN6Test162S2E = available_externally +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test161SE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test162S2E = available_externally struct S { __attribute__((visibility("hidden"))) virtual void doStuff(); @@ -395,6 +411,10 @@ // This test checks if we emit vtables opportunistically. // CHECK-TEST17-DAG: @_ZTVN6Test171AE = available_externally // CHECK-TEST17-DAG: @_ZTVN6Test171BE = external +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171AE = available_externally +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171BE = available_externally +// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD1Ev( +// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD0Ev( struct A { virtual void key(); Index: clang/lib/Frontend/CompilerInvocation.cpp === --- clang/lib/Front
[PATCH] D47099: Disable casting of alloca for ActiveFlag
rjmccall added a comment. In https://reviews.llvm.org/D47099#1105574, @yaxunl wrote: > In https://reviews.llvm.org/D47099#1105493, @rjmccall wrote: > > > Maybe there should just be a method that makes a primitive alloca without > > the casting, and then you can call that in CreateTempAlloca. > > > In many cases we still need to call CreateTempAlloca with cast enabled, since > we are not certain there is only load from it and store to it. Any time it is > stored to another memory location or passed to another function (e.g. > constructor/destructor), it needs to be a pointer to the language's default > address space since the language sees it that way. Yes, I understand that. But there are some cases, like this, that do not need to produce something in `LangAS::Default`, and extracting out a method that just does an `alloca` without the unnecessary cast seems sensible. > An alternative fix would be just let ActiveFlag to be llvm::Value instead of > llvm::AllocaInst, since it does not really need to be an AllocaInst. I don't care at all about the type of `ActiveFlag`, but if we can generate better code at -O0 by avoiding the casts in situations where we obviously don't need them, we should do it. https://reviews.llvm.org/D47099 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D47103: Implement strip.invariant.group
Prazek updated this revision to Diff 147683. Prazek added a comment. introduced mayBeDynamicClass and added more tests Repository: rL LLVM https://reviews.llvm.org/D47103 Files: clang/include/clang/AST/DeclCXX.h clang/lib/CodeGen/CGExpr.cpp clang/lib/CodeGen/CGExprScalar.cpp clang/test/CodeGenCXX/strict-vtable-pointers.cpp llvm/docs/LangRef.rst llvm/include/llvm/IR/IRBuilder.h llvm/include/llvm/IR/Intrinsics.td llvm/lib/Analysis/CaptureTracking.cpp llvm/lib/Analysis/ConstantFolding.cpp llvm/lib/Analysis/ValueTracking.cpp llvm/lib/CodeGen/CodeGenPrepare.cpp llvm/lib/CodeGen/SelectionDAG/FastISel.cpp llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp llvm/lib/IR/Value.cpp llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp llvm/test/Analysis/ValueTracking/invariant.group.ll llvm/test/CodeGen/Generic/intrinsics.ll llvm/test/Other/invariant.group.ll llvm/test/Other/launder.invariant.group.ll llvm/test/Transforms/CodeGenPrepare/invariant.group.ll llvm/test/Transforms/DeadStoreElimination/launder.invariant.group.ll llvm/test/Transforms/FunctionAttrs/nocapture.ll llvm/test/Transforms/GVN/invariant.group.ll llvm/test/Transforms/GlobalOpt/invariant.group.barrier.ll llvm/test/Transforms/GlobalOpt/invariant.group.ll llvm/test/Transforms/InstCombine/invariant.group.ll llvm/test/Transforms/NewGVN/invariant.group.ll Index: llvm/test/Transforms/NewGVN/invariant.group.ll === --- llvm/test/Transforms/NewGVN/invariant.group.ll +++ llvm/test/Transforms/NewGVN/invariant.group.ll @@ -52,6 +52,19 @@ ret i8 %b } +; CHECK-LABEL: define i1 @proveEqualityForStrip( +define i1 @proveEqualityForStrip(i8* %a) { +; FIXME: The first call could be also removed by GVN. Right now +; DCE removes it. The second call is CSE'd with the first one. +; CHECK: %b1 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a) + %b1 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a) +; CHECK-NOT: llvm.strip.invariant.group + %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a) + %r = icmp eq i8* %b1, %b2 +; CHECK: ret i1 true + ret i1 %r +} + ; CHECK-LABEL: define i8 @unoptimizable1() { define i8 @unoptimizable1() { entry: Index: llvm/test/Transforms/InstCombine/invariant.group.ll === --- llvm/test/Transforms/InstCombine/invariant.group.ll +++ llvm/test/Transforms/InstCombine/invariant.group.ll @@ -1,5 +1,6 @@ ; RUN: opt -instcombine -S < %s | FileCheck %s + ; CHECK-LABEL: define i8* @simplifyNullLaunder() define i8* @simplifyNullLaunder() { ; CHECK-NEXT: ret i8* null @@ -29,6 +30,39 @@ ret i8 addrspace(42)* %b2 } - declare i8* @llvm.launder.invariant.group.p0i8(i8*) declare i8 addrspace(42)* @llvm.launder.invariant.group.p42i8(i8 addrspace(42)*) + + +; CHECK-LABEL: define i8* @simplifyNullStrip() +define i8* @simplifyNullStrip() { +; CHECK-NEXT: ret i8* null + %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* null) + ret i8* %b2 +} + +; CHECK-LABEL: define i8 addrspace(42)* @dontsimplifyNullStripForDifferentAddrspace() +define i8 addrspace(42)* @dontsimplifyNullStripForDifferentAddrspace() { +; CHECK: %b2 = call i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)* null) +; CHECK: ret i8 addrspace(42)* %b2 + %b2 = call i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)* null) + ret i8 addrspace(42)* %b2 +} + +; CHECK-LABEL: define i8* @simplifyUndefStrip() +define i8* @simplifyUndefStrip() { +; CHECK-NEXT: ret i8* undef + %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* undef) + ret i8* %b2 +} + +; CHECK-LABEL: define i8 addrspace(42)* @simplifyUndefStrip2() +define i8 addrspace(42)* @simplifyUndefStrip2() { +; CHECK-NEXT: ret i8 addrspace(42)* undef + %b2 = call i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)* undef) + ret i8 addrspace(42)* %b2 +} + +declare i8* @llvm.strip.invariant.group.p0i8(i8*) +declare i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)*) + Index: llvm/test/Transforms/GlobalOpt/invariant.group.ll === --- llvm/test/Transforms/GlobalOpt/invariant.group.ll +++ llvm/test/Transforms/GlobalOpt/invariant.group.ll @@ -27,46 +27,46 @@ define void @_optimizable() { enter: %valptr = alloca i32 - + %val = call i32 @TheAnswerToLifeTheUniverseAndEverything() store i32 %val, i32* @tmp store i32 %val, i32* %valptr - + %0 = bitcast i32* %valptr to i8* %barr = call i8* @llvm.launder.invariant.group(i8* %0) %1 = bitcast i8* %barr to i32* - + %val2 = load i32, i32* %1 store i32 %val2, i32* @tmp2 ret void } ; We can't step through launder.invariant.group here, because that would change ; this load in @usage_of_globals() -; val = load i32, i32* %ptrVal, !invariant.group !0 -; into +; val = load i32, i32* %ptrVal, !invariant.group !0 +; into ; %val =
[PATCH] D47103: Implement strip.invariant.group
xbolva00 added inline comments. Comment at: clang/include/clang/AST/DeclCXX.h:778 + bool mayBeDynamicClass() const { +return !isCompleteDefinition() || isDynamicClass(); maybeDynamicClass? https://github.com/llvm-mirror/llvm/search?utf8=%E2%9C%93&q=maybe&type= Repository: rL LLVM https://reviews.llvm.org/D47103 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D47111: Implement monotonic_buffer_resource in
Quuxplusone created this revision. Quuxplusone added a reviewer: EricWF. Herald added a subscriber: cfe-commits. (https://reviews.llvm.org/D47090 included this in ``; at Eric's request, I've split this out into its own patch applied to the existing `` instead.) Repository: rCXX libc++ https://reviews.llvm.org/D47111 Files: include/experimental/memory_resource src/experimental/memory_resource.cpp test/std/experimental/memory/memory.resource.monotonic.buffer/monotonic_buffer.pass.cpp Index: test/std/experimental/memory/memory.resource.monotonic.buffer/monotonic_buffer.pass.cpp === --- /dev/null +++ test/std/experimental/memory/memory.resource.monotonic.buffer/monotonic_buffer.pass.cpp @@ -0,0 +1,408 @@ +//===--===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===--===// + +// UNSUPPORTED: c++98, c++03 + +// + +// class monotonic_buffer_resource + +#include +#include +#include +#include + +#include "count_new.hpp" + +struct assert_on_compare : public std::experimental::pmr::memory_resource +{ +protected: +virtual void * do_allocate(size_t, size_t) +{ assert(false); } + +virtual void do_deallocate(void *, size_t, size_t) +{ assert(false); } + +virtual bool do_is_equal(std::experimental::pmr::memory_resource const &) const noexcept +{ assert(false); } +}; + +struct repointable_resource : public std::experimental::pmr::memory_resource +{ +std::experimental::pmr::memory_resource *which; + +explicit repointable_resource(std::experimental::pmr::memory_resource *res) : which(res) {} + +protected: +virtual void *do_allocate(size_t size, size_t align) +{ return which->allocate(size, align); } + +virtual void do_deallocate(void *p, size_t size, size_t align) +{ return which->deallocate(p, size, align); } + +virtual bool do_is_equal(std::experimental::pmr::memory_resource const &rhs) const noexcept +{ return which->is_equal(rhs); } +}; + +void test_construction_with_default_resource() +{ +std::experimental::pmr::memory_resource *expected = std::experimental::pmr::null_memory_resource(); +std::experimental::pmr::set_default_resource(expected); +{ +char buffer[16]; +std::experimental::pmr::monotonic_buffer_resource r1; +std::experimental::pmr::monotonic_buffer_resource r2(16); +std::experimental::pmr::monotonic_buffer_resource r3(buffer, sizeof buffer); +assert(r1.upstream_resource() == expected); +assert(r2.upstream_resource() == expected); +assert(r3.upstream_resource() == expected); +} + +expected = std::experimental::pmr::new_delete_resource(); +std::experimental::pmr::set_default_resource(expected); +{ +char buffer[16]; +std::experimental::pmr::monotonic_buffer_resource r1; +std::experimental::pmr::monotonic_buffer_resource r2(16); +std::experimental::pmr::monotonic_buffer_resource r3(buffer, sizeof buffer); +assert(r1.upstream_resource() == expected); +assert(r2.upstream_resource() == expected); +assert(r3.upstream_resource() == expected); +} +} + +void test_construction_without_buffer() +{ +// Constructing a monotonic_buffer_resource should not cause allocations +// by itself; the resource should wait to allocate until an allocation is +// requested. + +globalMemCounter.reset(); +std::experimental::pmr::set_default_resource(std::experimental::pmr::new_delete_resource()); + +std::experimental::pmr::monotonic_buffer_resource r1; +assert(globalMemCounter.checkNewCalledEq(0)); + +std::experimental::pmr::monotonic_buffer_resource r2(1024); +assert(globalMemCounter.checkNewCalledEq(0)); + +std::experimental::pmr::monotonic_buffer_resource r3(1024, std::experimental::pmr::new_delete_resource()); +assert(globalMemCounter.checkNewCalledEq(0)); +} + +void test_equality() +{ +// Same object +{ +std::experimental::pmr::monotonic_buffer_resource r1; +std::experimental::pmr::monotonic_buffer_resource r2; +assert(r1 == r1); +assert(r1 != r2); + +std::experimental::pmr::memory_resource & p1 = r1; +std::experimental::pmr::memory_resource & p2 = r2; +assert(p1 == p1); +assert(p1 != p2); +assert(p1 == r1); +assert(r1 == p1); +assert(p1 != r2); +assert(r2 != p1); +} +// Different types +{ +std::experimental::pmr::monotonic_buffer_resource mono1; +std::experimental::pmr::memory_resource & r1 = mono1; +assert_on_compare c; +std::experimental::pmr::memory_resource & r2 = c; +
[PATCH] D47103: Implement strip.invariant.group
Prazek updated this revision to Diff 147684. Prazek added a comment. Changed comments Repository: rL LLVM https://reviews.llvm.org/D47103 Files: clang/include/clang/AST/DeclCXX.h clang/lib/CodeGen/CGExpr.cpp clang/lib/CodeGen/CGExprScalar.cpp clang/test/CodeGenCXX/strict-vtable-pointers.cpp llvm/docs/LangRef.rst llvm/include/llvm/IR/IRBuilder.h llvm/include/llvm/IR/Intrinsics.td llvm/lib/Analysis/BasicAliasAnalysis.cpp llvm/lib/Analysis/CaptureTracking.cpp llvm/lib/Analysis/ConstantFolding.cpp llvm/lib/Analysis/ValueTracking.cpp llvm/lib/CodeGen/CodeGenPrepare.cpp llvm/lib/CodeGen/SelectionDAG/FastISel.cpp llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp llvm/lib/IR/Value.cpp llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp llvm/test/Analysis/ValueTracking/invariant.group.ll llvm/test/CodeGen/Generic/intrinsics.ll llvm/test/Other/invariant.group.ll llvm/test/Other/launder.invariant.group.ll llvm/test/Transforms/CodeGenPrepare/invariant.group.ll llvm/test/Transforms/DeadStoreElimination/launder.invariant.group.ll llvm/test/Transforms/FunctionAttrs/nocapture.ll llvm/test/Transforms/GVN/invariant.group.ll llvm/test/Transforms/GlobalOpt/invariant.group.barrier.ll llvm/test/Transforms/GlobalOpt/invariant.group.ll llvm/test/Transforms/InstCombine/invariant.group.ll llvm/test/Transforms/NewGVN/invariant.group.ll Index: llvm/test/Transforms/NewGVN/invariant.group.ll === --- llvm/test/Transforms/NewGVN/invariant.group.ll +++ llvm/test/Transforms/NewGVN/invariant.group.ll @@ -52,6 +52,19 @@ ret i8 %b } +; CHECK-LABEL: define i1 @proveEqualityForStrip( +define i1 @proveEqualityForStrip(i8* %a) { +; FIXME: The first call could be also removed by GVN. Right now +; DCE removes it. The second call is CSE'd with the first one. +; CHECK: %b1 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a) + %b1 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a) +; CHECK-NOT: llvm.strip.invariant.group + %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a) + %r = icmp eq i8* %b1, %b2 +; CHECK: ret i1 true + ret i1 %r +} + ; CHECK-LABEL: define i8 @unoptimizable1() { define i8 @unoptimizable1() { entry: Index: llvm/test/Transforms/InstCombine/invariant.group.ll === --- llvm/test/Transforms/InstCombine/invariant.group.ll +++ llvm/test/Transforms/InstCombine/invariant.group.ll @@ -1,5 +1,6 @@ ; RUN: opt -instcombine -S < %s | FileCheck %s + ; CHECK-LABEL: define i8* @simplifyNullLaunder() define i8* @simplifyNullLaunder() { ; CHECK-NEXT: ret i8* null @@ -29,6 +30,39 @@ ret i8 addrspace(42)* %b2 } - declare i8* @llvm.launder.invariant.group.p0i8(i8*) declare i8 addrspace(42)* @llvm.launder.invariant.group.p42i8(i8 addrspace(42)*) + + +; CHECK-LABEL: define i8* @simplifyNullStrip() +define i8* @simplifyNullStrip() { +; CHECK-NEXT: ret i8* null + %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* null) + ret i8* %b2 +} + +; CHECK-LABEL: define i8 addrspace(42)* @dontsimplifyNullStripForDifferentAddrspace() +define i8 addrspace(42)* @dontsimplifyNullStripForDifferentAddrspace() { +; CHECK: %b2 = call i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)* null) +; CHECK: ret i8 addrspace(42)* %b2 + %b2 = call i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)* null) + ret i8 addrspace(42)* %b2 +} + +; CHECK-LABEL: define i8* @simplifyUndefStrip() +define i8* @simplifyUndefStrip() { +; CHECK-NEXT: ret i8* undef + %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* undef) + ret i8* %b2 +} + +; CHECK-LABEL: define i8 addrspace(42)* @simplifyUndefStrip2() +define i8 addrspace(42)* @simplifyUndefStrip2() { +; CHECK-NEXT: ret i8 addrspace(42)* undef + %b2 = call i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)* undef) + ret i8 addrspace(42)* %b2 +} + +declare i8* @llvm.strip.invariant.group.p0i8(i8*) +declare i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)*) + Index: llvm/test/Transforms/GlobalOpt/invariant.group.ll === --- llvm/test/Transforms/GlobalOpt/invariant.group.ll +++ llvm/test/Transforms/GlobalOpt/invariant.group.ll @@ -27,46 +27,46 @@ define void @_optimizable() { enter: %valptr = alloca i32 - + %val = call i32 @TheAnswerToLifeTheUniverseAndEverything() store i32 %val, i32* @tmp store i32 %val, i32* %valptr - + %0 = bitcast i32* %valptr to i8* %barr = call i8* @llvm.launder.invariant.group(i8* %0) %1 = bitcast i8* %barr to i32* - + %val2 = load i32, i32* %1 store i32 %val2, i32* @tmp2 ret void } ; We can't step through launder.invariant.group here, because that would change ; this load in @usage_of_globals() -; val = load i32, i32* %ptrVal, !invariant.group !0 -; into +; val = load i32, i32* %ptrVal, !invariant.group !0 +; into
[PATCH] D47103: Implement strip.invariant.group
Prazek updated this revision to Diff 147688. Prazek added a comment. After rebasing Repository: rL LLVM https://reviews.llvm.org/D47103 Files: clang/include/clang/AST/DeclCXX.h clang/lib/CodeGen/CGExpr.cpp clang/lib/CodeGen/CGExprScalar.cpp clang/test/CodeGenCXX/strict-vtable-pointers.cpp llvm/docs/LangRef.rst llvm/include/llvm/IR/IRBuilder.h llvm/include/llvm/IR/Intrinsics.td llvm/lib/Analysis/BasicAliasAnalysis.cpp llvm/lib/Analysis/ConstantFolding.cpp llvm/lib/Analysis/ValueTracking.cpp llvm/lib/CodeGen/CodeGenPrepare.cpp llvm/lib/CodeGen/SelectionDAG/FastISel.cpp llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp llvm/lib/IR/Value.cpp llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp llvm/test/Analysis/ValueTracking/invariant.group.ll llvm/test/CodeGen/Generic/intrinsics.ll llvm/test/Other/invariant.group.ll llvm/test/Other/launder.invariant.group.ll llvm/test/Transforms/CodeGenPrepare/invariant.group.ll llvm/test/Transforms/DeadStoreElimination/launder.invariant.group.ll llvm/test/Transforms/FunctionAttrs/nocapture.ll llvm/test/Transforms/GVN/invariant.group.ll llvm/test/Transforms/GlobalOpt/invariant.group.barrier.ll llvm/test/Transforms/GlobalOpt/invariant.group.ll llvm/test/Transforms/InstCombine/invariant.group.ll llvm/test/Transforms/NewGVN/invariant.group.ll Index: llvm/test/Transforms/NewGVN/invariant.group.ll === --- llvm/test/Transforms/NewGVN/invariant.group.ll +++ llvm/test/Transforms/NewGVN/invariant.group.ll @@ -52,6 +52,19 @@ ret i8 %b } +; CHECK-LABEL: define i1 @proveEqualityForStrip( +define i1 @proveEqualityForStrip(i8* %a) { +; FIXME: The first call could be also removed by GVN. Right now +; DCE removes it. The second call is CSE'd with the first one. +; CHECK: %b1 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a) + %b1 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a) +; CHECK-NOT: llvm.strip.invariant.group + %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a) + %r = icmp eq i8* %b1, %b2 +; CHECK: ret i1 true + ret i1 %r +} + ; CHECK-LABEL: define i8 @unoptimizable1() { define i8 @unoptimizable1() { entry: Index: llvm/test/Transforms/InstCombine/invariant.group.ll === --- llvm/test/Transforms/InstCombine/invariant.group.ll +++ llvm/test/Transforms/InstCombine/invariant.group.ll @@ -1,5 +1,6 @@ ; RUN: opt -instcombine -S < %s | FileCheck %s + ; CHECK-LABEL: define i8* @simplifyNullLaunder() define i8* @simplifyNullLaunder() { ; CHECK-NEXT: ret i8* null @@ -29,6 +30,39 @@ ret i8 addrspace(42)* %b2 } - declare i8* @llvm.launder.invariant.group.p0i8(i8*) declare i8 addrspace(42)* @llvm.launder.invariant.group.p42i8(i8 addrspace(42)*) + + +; CHECK-LABEL: define i8* @simplifyNullStrip() +define i8* @simplifyNullStrip() { +; CHECK-NEXT: ret i8* null + %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* null) + ret i8* %b2 +} + +; CHECK-LABEL: define i8 addrspace(42)* @dontsimplifyNullStripForDifferentAddrspace() +define i8 addrspace(42)* @dontsimplifyNullStripForDifferentAddrspace() { +; CHECK: %b2 = call i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)* null) +; CHECK: ret i8 addrspace(42)* %b2 + %b2 = call i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)* null) + ret i8 addrspace(42)* %b2 +} + +; CHECK-LABEL: define i8* @simplifyUndefStrip() +define i8* @simplifyUndefStrip() { +; CHECK-NEXT: ret i8* undef + %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* undef) + ret i8* %b2 +} + +; CHECK-LABEL: define i8 addrspace(42)* @simplifyUndefStrip2() +define i8 addrspace(42)* @simplifyUndefStrip2() { +; CHECK-NEXT: ret i8 addrspace(42)* undef + %b2 = call i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)* undef) + ret i8 addrspace(42)* %b2 +} + +declare i8* @llvm.strip.invariant.group.p0i8(i8*) +declare i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)*) + Index: llvm/test/Transforms/GlobalOpt/invariant.group.ll === --- llvm/test/Transforms/GlobalOpt/invariant.group.ll +++ llvm/test/Transforms/GlobalOpt/invariant.group.ll @@ -27,46 +27,46 @@ define void @_optimizable() { enter: %valptr = alloca i32 - + %val = call i32 @TheAnswerToLifeTheUniverseAndEverything() store i32 %val, i32* @tmp store i32 %val, i32* %valptr - + %0 = bitcast i32* %valptr to i8* %barr = call i8* @llvm.launder.invariant.group(i8* %0) %1 = bitcast i8* %barr to i32* - + %val2 = load i32, i32* %1 store i32 %val2, i32* @tmp2 ret void } ; We can't step through launder.invariant.group here, because that would change ; this load in @usage_of_globals() -; val = load i32, i32* %ptrVal, !invariant.group !0 -; into +; val = load i32, i32* %ptrVal, !invariant.group !0 +; into ; %val = load i32, i32* @tmp3, !invarian
[PATCH] D47103: Implement strip.invariant.group
Prazek updated this revision to Diff 147691. Prazek added a comment. rebase Repository: rL LLVM https://reviews.llvm.org/D47103 Files: clang/include/clang/AST/DeclCXX.h clang/lib/CodeGen/CGExpr.cpp clang/lib/CodeGen/CGExprScalar.cpp clang/test/CodeGenCXX/strict-vtable-pointers.cpp llvm/docs/LangRef.rst llvm/include/llvm/IR/IRBuilder.h llvm/include/llvm/IR/Intrinsics.td llvm/lib/Analysis/BasicAliasAnalysis.cpp llvm/lib/Analysis/ConstantFolding.cpp llvm/lib/Analysis/ValueTracking.cpp llvm/lib/CodeGen/CodeGenPrepare.cpp llvm/lib/CodeGen/SelectionDAG/FastISel.cpp llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp llvm/lib/IR/Value.cpp llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp llvm/test/Analysis/ValueTracking/invariant.group.ll llvm/test/CodeGen/Generic/intrinsics.ll llvm/test/Other/invariant.group.ll llvm/test/Other/launder.invariant.group.ll llvm/test/Transforms/CodeGenPrepare/invariant.group.ll llvm/test/Transforms/DeadStoreElimination/launder.invariant.group.ll llvm/test/Transforms/FunctionAttrs/nocapture.ll llvm/test/Transforms/GVN/invariant.group.ll llvm/test/Transforms/GlobalOpt/invariant.group.barrier.ll llvm/test/Transforms/GlobalOpt/invariant.group.ll llvm/test/Transforms/InstCombine/invariant.group.ll llvm/test/Transforms/NewGVN/invariant.group.ll Index: llvm/test/Transforms/NewGVN/invariant.group.ll === --- llvm/test/Transforms/NewGVN/invariant.group.ll +++ llvm/test/Transforms/NewGVN/invariant.group.ll @@ -52,6 +52,19 @@ ret i8 %b } +; CHECK-LABEL: define i1 @proveEqualityForStrip( +define i1 @proveEqualityForStrip(i8* %a) { +; FIXME: The first call could be also removed by GVN. Right now +; DCE removes it. The second call is CSE'd with the first one. +; CHECK: %b1 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a) + %b1 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a) +; CHECK-NOT: llvm.strip.invariant.group + %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a) + %r = icmp eq i8* %b1, %b2 +; CHECK: ret i1 true + ret i1 %r +} + ; CHECK-LABEL: define i8 @unoptimizable1() { define i8 @unoptimizable1() { entry: Index: llvm/test/Transforms/InstCombine/invariant.group.ll === --- llvm/test/Transforms/InstCombine/invariant.group.ll +++ llvm/test/Transforms/InstCombine/invariant.group.ll @@ -1,5 +1,6 @@ ; RUN: opt -instcombine -S < %s | FileCheck %s + ; CHECK-LABEL: define i8* @simplifyNullLaunder() define i8* @simplifyNullLaunder() { ; CHECK-NEXT: ret i8* null @@ -29,6 +30,39 @@ ret i8 addrspace(42)* %b2 } - declare i8* @llvm.launder.invariant.group.p0i8(i8*) declare i8 addrspace(42)* @llvm.launder.invariant.group.p42i8(i8 addrspace(42)*) + + +; CHECK-LABEL: define i8* @simplifyNullStrip() +define i8* @simplifyNullStrip() { +; CHECK-NEXT: ret i8* null + %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* null) + ret i8* %b2 +} + +; CHECK-LABEL: define i8 addrspace(42)* @dontsimplifyNullStripForDifferentAddrspace() +define i8 addrspace(42)* @dontsimplifyNullStripForDifferentAddrspace() { +; CHECK: %b2 = call i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)* null) +; CHECK: ret i8 addrspace(42)* %b2 + %b2 = call i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)* null) + ret i8 addrspace(42)* %b2 +} + +; CHECK-LABEL: define i8* @simplifyUndefStrip() +define i8* @simplifyUndefStrip() { +; CHECK-NEXT: ret i8* undef + %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* undef) + ret i8* %b2 +} + +; CHECK-LABEL: define i8 addrspace(42)* @simplifyUndefStrip2() +define i8 addrspace(42)* @simplifyUndefStrip2() { +; CHECK-NEXT: ret i8 addrspace(42)* undef + %b2 = call i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)* undef) + ret i8 addrspace(42)* %b2 +} + +declare i8* @llvm.strip.invariant.group.p0i8(i8*) +declare i8 addrspace(42)* @llvm.strip.invariant.group.p42i8(i8 addrspace(42)*) + Index: llvm/test/Transforms/GlobalOpt/invariant.group.ll === --- llvm/test/Transforms/GlobalOpt/invariant.group.ll +++ llvm/test/Transforms/GlobalOpt/invariant.group.ll @@ -27,46 +27,46 @@ define void @_optimizable() { enter: %valptr = alloca i32 - + %val = call i32 @TheAnswerToLifeTheUniverseAndEverything() store i32 %val, i32* @tmp store i32 %val, i32* %valptr - + %0 = bitcast i32* %valptr to i8* %barr = call i8* @llvm.launder.invariant.group(i8* %0) %1 = bitcast i8* %barr to i32* - + %val2 = load i32, i32* %1 store i32 %val2, i32* @tmp2 ret void } ; We can't step through launder.invariant.group here, because that would change ; this load in @usage_of_globals() -; val = load i32, i32* %ptrVal, !invariant.group !0 -; into +; val = load i32, i32* %ptrVal, !invariant.group !0 +; into ; %val = load i32, i32* @tmp3, !invariant.group
[PATCH] D44931: [WebAssembly] Use Windows EH instructions for Wasm EH
aheejin updated this revision to Diff 147695. aheejin added a comment. - Make `wasm.get.exception/selector` intrinsics take a token argument Repository: rC Clang https://reviews.llvm.org/D44931 Files: lib/CodeGen/CGCXXABI.h lib/CodeGen/CGCleanup.cpp lib/CodeGen/CGCleanup.h lib/CodeGen/CGException.cpp lib/CodeGen/CodeGenFunction.h lib/CodeGen/ItaniumCXXABI.cpp lib/CodeGen/MicrosoftCXXABI.cpp test/CodeGenCXX/wasm-eh.cpp Index: test/CodeGenCXX/wasm-eh.cpp === --- /dev/null +++ test/CodeGenCXX/wasm-eh.cpp @@ -0,0 +1,384 @@ +// RUN: %clang_cc1 %s -triple wasm32-unknown-unknown -fms-extensions -fexceptions -fcxx-exceptions -emit-llvm -o - -std=c++11 | FileCheck %s +// RUN: %clang_cc1 %s -triple wasm64-unknown-unknown -fms-extensions -fexceptions -fcxx-exceptions -emit-llvm -o - -std=c++11 | FileCheck %s + +void may_throw(); +void dont_throw() noexcept; + +struct Cleanup { + ~Cleanup() { dont_throw(); } +}; + +// Multiple catch clauses w/o catch-all +void test0() { + try { +may_throw(); + } catch (int) { +dont_throw(); + } catch (double) { +dont_throw(); + } +} + +// CHECK-LABEL: define void @_Z5test0v() {{.*}} personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) + +// CHECK: %[[INT_ALLOCA:.*]] = alloca i32 +// CHECK: invoke void @_Z9may_throwv() +// CHECK-NEXT: to label %[[NORMAL_BB:.*]] unwind label %[[CATCHDISPATCH_BB:.*]] + +// CHECK: [[CATCHDISPATCH_BB]]: +// CHECK-NEXT: %[[CATCHSWITCH:.*]] = catchswitch within none [label %[[CATCHSTART_BB:.*]]] unwind to caller + +// CHECK: [[CATCHSTART_BB]]: +// CHECK-NEXT: %[[CATCHPAD:.*]] = catchpad within %[[CATCHSWITCH]] [i8* bitcast (i8** @_ZTIi to i8*), i8* bitcast (i8** @_ZTId to i8*)] +// CHECK-NEXT: %[[EXN:.*]] = call i8* @llvm.wasm.get.exception() +// CHECK-NEXT: store i8* %[[EXN]], i8** %exn.slot +// CHECK-NEXT: %[[SELECTOR:.*]] = call i32 @llvm.wasm.get.ehselector() +// CHECK-NEXT: %[[TYPEID:.*]] = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) #2 +// CHECK-NEXT: %[[MATCHES:.*]] = icmp eq i32 %[[SELECTOR]], %[[TYPEID]] +// CHECK-NEXT: br i1 %[[MATCHES]], label %[[CATCH_INT_BB:.*]], label %[[CATCH_FALLTHROUGH_BB:.*]] + +// CHECK: [[CATCH_INT_BB]]: +// CHECK-NEXT: %[[EXN:.*]] = load i8*, i8** %exn.slot +// CHECK-NEXT: %[[ADDR:.*]] = call i8* @__cxa_begin_catch(i8* %[[EXN]]) {{.*}} [ "funclet"(token %[[CATCHPAD]]) ] +// CHECK-NEXT: %[[ADDR_CAST:.*]] = bitcast i8* %[[ADDR]] to i32* +// CHECK-NEXT: %[[INT_VAL:.*]] = load i32, i32* %[[ADDR_CAST]] +// CHECK-NEXT: store i32 %[[INT_VAL]], i32* %[[INT_ALLOCA]] +// CHECK-NEXT: call void @_Z10dont_throwv() {{.*}} [ "funclet"(token %[[CATCHPAD]]) ] +// CHECK-NEXT: call void @__cxa_end_catch() {{.*}} [ "funclet"(token %[[CATCHPAD]]) ] +// CHECK-NEXT: catchret from %[[CATCHPAD]] to label %[[CATCHRET_DEST_BB0:.*]] + +// CHECK: [[CATCHRET_DEST_BB0]]: +// CHECK-NEXT: br label %[[TRY_CONT_BB:.*]] + +// CHECK: [[CATCH_FALLTHROUGH_BB]] +// CHECK-NEXT: %[[TYPEID:.*]] = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTId to i8*)) #2 +// CHECK-NEXT: %[[MATCHES:.*]] = icmp eq i32 %[[SELECTOR]], %[[TYPEID]] +// CHECK-NEXT: br i1 %[[MATCHES]], label %[[CATCH_FLOAT_BB:.*]], label %[[RETHROW_BB:.*]] + +// CHECK: [[CATCH_FLOAT_BB]]: +// CHECK: catchret from %[[CATCHPAD]] to label %[[CATCHRET_DEST_BB1:.*]] + +// CHECK: [[CATCHRET_DEST_BB1]]: +// CHECK-NEXT: br label %[[TRY_CONT_BB]] + +// CHECK: [[RETHROW_BB]]: +// CHECK-NEXT: call void @__cxa_rethrow() {{.*}} [ "funclet"(token %[[CATCHPAD]]) ] +// CHECK-NEXT: unreachable + +// Single catch-all +void test1() { + try { +may_throw(); + } catch (...) { +dont_throw(); + } +} + +// CATCH-LABEL: @_Z5test1v() + +// CHECK: %[[CATCHSWITCH:.*]] = catchswitch within none [label %[[CATCHSTART_BB:.*]]] unwind to caller + +// CHECK: [[CATCHSTART_BB]]: +// CHECK-NEXT: %[[CATCHPAD:.*]] = catchpad within %[[CATCHSWITCH]] [i8* null] +// CHECK: br label %[[CATCH_ALL_BB:.*]] + +// CHECK: [[CATCH_ALL_BB]]: +// CHECK: catchret from %[[CATCHPAD]] to label + +// Multiple catch clauses w/ catch-all +void test2() { + try { +may_throw(); + } catch (int) { +dont_throw(); + } catch (...) { +dont_throw(); + } +} + +// CHECK-LABEL: @_Z5test2v() + +// CHECK: %[[CATCHSWITCH:.*]] = catchswitch within none [label %[[CATCHSTART_BB:.*]]] unwind to caller + +// CHECK: [[CATCHSTART_BB]]: +// CHECK-NEXT: %[[CATCHPAD:.*]] = catchpad within %[[CATCHSWITCH]] [i8* bitcast (i8** @_ZTIi to i8*), i8* null] +// CHECK: br i1 %{{.*}}, label %[[CATCH_INT_BB:.*]], label %[[CATCH_ALL_BB:.*]] + +// CHECK: [[CATCH_INT_BB]]: +// CHECK: catchret from %[[CATCHPAD]] to label + +// CHECK: [[CATCH_ALL_BB]]: +// CHECK: catchret from %[[CATCHPAD]] to label + +// Cleanup +void test3() { + Cleanup c; + may_throw(); +} + +// CHECK-LABEL: @_Z5test3v() + +// CHECK: invoke void @_Z9may_throwv() +// CHECK-NEXT:
[PATCH] D44931: [WebAssembly] Use Windows EH instructions for Wasm EH
aheejin updated this revision to Diff 147696. aheejin added a comment. Test case fix was missing in the last commit Repository: rC Clang https://reviews.llvm.org/D44931 Files: lib/CodeGen/CGCXXABI.h lib/CodeGen/CGCleanup.cpp lib/CodeGen/CGCleanup.h lib/CodeGen/CGException.cpp lib/CodeGen/CodeGenFunction.h lib/CodeGen/ItaniumCXXABI.cpp lib/CodeGen/MicrosoftCXXABI.cpp test/CodeGenCXX/wasm-eh.cpp Index: test/CodeGenCXX/wasm-eh.cpp === --- /dev/null +++ test/CodeGenCXX/wasm-eh.cpp @@ -0,0 +1,384 @@ +// RUN: %clang_cc1 %s -triple wasm32-unknown-unknown -fms-extensions -fexceptions -fcxx-exceptions -emit-llvm -o - -std=c++11 | FileCheck %s +// RUN: %clang_cc1 %s -triple wasm64-unknown-unknown -fms-extensions -fexceptions -fcxx-exceptions -emit-llvm -o - -std=c++11 | FileCheck %s + +void may_throw(); +void dont_throw() noexcept; + +struct Cleanup { + ~Cleanup() { dont_throw(); } +}; + +// Multiple catch clauses w/o catch-all +void test0() { + try { +may_throw(); + } catch (int) { +dont_throw(); + } catch (double) { +dont_throw(); + } +} + +// CHECK-LABEL: define void @_Z5test0v() {{.*}} personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) + +// CHECK: %[[INT_ALLOCA:.*]] = alloca i32 +// CHECK: invoke void @_Z9may_throwv() +// CHECK-NEXT: to label %[[NORMAL_BB:.*]] unwind label %[[CATCHDISPATCH_BB:.*]] + +// CHECK: [[CATCHDISPATCH_BB]]: +// CHECK-NEXT: %[[CATCHSWITCH:.*]] = catchswitch within none [label %[[CATCHSTART_BB:.*]]] unwind to caller + +// CHECK: [[CATCHSTART_BB]]: +// CHECK-NEXT: %[[CATCHPAD:.*]] = catchpad within %[[CATCHSWITCH]] [i8* bitcast (i8** @_ZTIi to i8*), i8* bitcast (i8** @_ZTId to i8*)] +// CHECK-NEXT: %[[EXN:.*]] = call i8* @llvm.wasm.get.exception(token %[[CATCHPAD]]) +// CHECK-NEXT: store i8* %[[EXN]], i8** %exn.slot +// CHECK-NEXT: %[[SELECTOR:.*]] = call i32 @llvm.wasm.get.ehselector(token %[[CATCHPAD]]) +// CHECK-NEXT: %[[TYPEID:.*]] = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) #2 +// CHECK-NEXT: %[[MATCHES:.*]] = icmp eq i32 %[[SELECTOR]], %[[TYPEID]] +// CHECK-NEXT: br i1 %[[MATCHES]], label %[[CATCH_INT_BB:.*]], label %[[CATCH_FALLTHROUGH_BB:.*]] + +// CHECK: [[CATCH_INT_BB]]: +// CHECK-NEXT: %[[EXN:.*]] = load i8*, i8** %exn.slot +// CHECK-NEXT: %[[ADDR:.*]] = call i8* @__cxa_begin_catch(i8* %[[EXN]]) {{.*}} [ "funclet"(token %[[CATCHPAD]]) ] +// CHECK-NEXT: %[[ADDR_CAST:.*]] = bitcast i8* %[[ADDR]] to i32* +// CHECK-NEXT: %[[INT_VAL:.*]] = load i32, i32* %[[ADDR_CAST]] +// CHECK-NEXT: store i32 %[[INT_VAL]], i32* %[[INT_ALLOCA]] +// CHECK-NEXT: call void @_Z10dont_throwv() {{.*}} [ "funclet"(token %[[CATCHPAD]]) ] +// CHECK-NEXT: call void @__cxa_end_catch() {{.*}} [ "funclet"(token %[[CATCHPAD]]) ] +// CHECK-NEXT: catchret from %[[CATCHPAD]] to label %[[CATCHRET_DEST_BB0:.*]] + +// CHECK: [[CATCHRET_DEST_BB0]]: +// CHECK-NEXT: br label %[[TRY_CONT_BB:.*]] + +// CHECK: [[CATCH_FALLTHROUGH_BB]] +// CHECK-NEXT: %[[TYPEID:.*]] = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTId to i8*)) #2 +// CHECK-NEXT: %[[MATCHES:.*]] = icmp eq i32 %[[SELECTOR]], %[[TYPEID]] +// CHECK-NEXT: br i1 %[[MATCHES]], label %[[CATCH_FLOAT_BB:.*]], label %[[RETHROW_BB:.*]] + +// CHECK: [[CATCH_FLOAT_BB]]: +// CHECK: catchret from %[[CATCHPAD]] to label %[[CATCHRET_DEST_BB1:.*]] + +// CHECK: [[CATCHRET_DEST_BB1]]: +// CHECK-NEXT: br label %[[TRY_CONT_BB]] + +// CHECK: [[RETHROW_BB]]: +// CHECK-NEXT: call void @__cxa_rethrow() {{.*}} [ "funclet"(token %[[CATCHPAD]]) ] +// CHECK-NEXT: unreachable + +// Single catch-all +void test1() { + try { +may_throw(); + } catch (...) { +dont_throw(); + } +} + +// CATCH-LABEL: @_Z5test1v() + +// CHECK: %[[CATCHSWITCH:.*]] = catchswitch within none [label %[[CATCHSTART_BB:.*]]] unwind to caller + +// CHECK: [[CATCHSTART_BB]]: +// CHECK-NEXT: %[[CATCHPAD:.*]] = catchpad within %[[CATCHSWITCH]] [i8* null] +// CHECK: br label %[[CATCH_ALL_BB:.*]] + +// CHECK: [[CATCH_ALL_BB]]: +// CHECK: catchret from %[[CATCHPAD]] to label + +// Multiple catch clauses w/ catch-all +void test2() { + try { +may_throw(); + } catch (int) { +dont_throw(); + } catch (...) { +dont_throw(); + } +} + +// CHECK-LABEL: @_Z5test2v() + +// CHECK: %[[CATCHSWITCH:.*]] = catchswitch within none [label %[[CATCHSTART_BB:.*]]] unwind to caller + +// CHECK: [[CATCHSTART_BB]]: +// CHECK-NEXT: %[[CATCHPAD:.*]] = catchpad within %[[CATCHSWITCH]] [i8* bitcast (i8** @_ZTIi to i8*), i8* null] +// CHECK: br i1 %{{.*}}, label %[[CATCH_INT_BB:.*]], label %[[CATCH_ALL_BB:.*]] + +// CHECK: [[CATCH_INT_BB]]: +// CHECK: catchret from %[[CATCHPAD]] to label + +// CHECK: [[CATCH_ALL_BB]]: +// CHECK: catchret from %[[CATCHPAD]] to label + +// Cleanup +void test3() { + Cleanup c; + may_throw(); +} + +// CHECK-LABEL: @_Z5test3v() + +// CHECK: invoke void @_Z9may_throwv() +//